From 8bf3b7586b110606a2db01e7b150647b416efb8b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 4 Feb 2014 13:02:33 -0800 Subject: [PATCH 01/42] initial movement of mesh/skeleton URLs out of data-server through avatar-mixer --- interface/src/Application.cpp | 11 ++- interface/src/DatagramProcessor.cpp | 15 ++-- interface/src/Menu.cpp | 26 ++++--- interface/src/avatar/AvatarManager.cpp | 91 +++++++++++++++---------- interface/src/avatar/AvatarManager.h | 11 +-- interface/src/avatar/MyAvatar.cpp | 10 +++ interface/src/avatar/MyAvatar.h | 2 + interface/src/avatar/Profile.cpp | 36 +--------- interface/src/avatar/Profile.h | 8 --- libraries/shared/src/DataServerClient.h | 2 - libraries/shared/src/PacketHeaders.h | 3 +- 11 files changed, 98 insertions(+), 117 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ca87c812d3..886d44c1fb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -242,6 +242,11 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes())); silentNodeTimer->moveToThread(_nodeThread); silentNodeTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000); + + // send the identity packet for our avatar each second to our avatar mixer + QTimer* identityPacketTimer = new QTimer(); + connect(identityPacketTimer, &QTimer::timeout, _myAvatar, &MyAvatar::sendIdentityPacket); + silentNodeTimer->start(1000); QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation); @@ -1855,12 +1860,6 @@ void Application::init() { } qDebug("Loaded settings"); - if (!_profile.getUsername().isEmpty()) { - // we have a username for this avatar, ask the data-server for the mesh URL for this avatar - DataServerClient::getValueForKeyAndUserString(DataServerKey::FaceMeshURL, _profile.getUserString(), &_profile); - DataServerClient::getValueForKeyAndUserString(DataServerKey::SkeletonURL, _profile.getUserString(), &_profile); - } - // Set up VoxelSystem after loading preferences so we can get the desired max voxel count _voxels.setMaxVoxels(Menu::getInstance()->getMaxVoxels()); _voxels.setUseVoxelShader(Menu::getInstance()->isOptionChecked(MenuOption::UseVoxelShader)); diff --git a/interface/src/DatagramProcessor.cpp b/interface/src/DatagramProcessor.cpp index 2938be80ea..741852922b 100644 --- a/interface/src/DatagramProcessor.cpp +++ b/interface/src/DatagramProcessor.cpp @@ -92,7 +92,8 @@ void DatagramProcessor::processDatagrams() { application->_metavoxels.processData(incomingPacket, senderSockAddr); break; case PacketTypeBulkAvatarData: - case PacketTypeKillAvatar: { + case PacketTypeKillAvatar: + case PacketTypeAvatarIdentity: { // update having heard from the avatar-mixer and record the bytes received SharedNodePointer avatarMixer = NodeList::getInstance()->nodeWithAddress(senderSockAddr); @@ -100,15 +101,9 @@ void DatagramProcessor::processDatagrams() { avatarMixer->setLastHeardMicrostamp(usecTimestampNow()); avatarMixer->recordBytesReceived(incomingPacket.size()); - if (packetTypeForPacket(incomingPacket) == PacketTypeBulkAvatarData) { - QMetaObject::invokeMethod(&application->getAvatarManager(), "processAvatarMixerDatagram", - Q_ARG(const QByteArray&, incomingPacket), - Q_ARG(const QWeakPointer&, avatarMixer)); - } else { - // this is an avatar kill, pass it to the application AvatarManager - QMetaObject::invokeMethod(&application->getAvatarManager(), "processKillAvatar", - Q_ARG(const QByteArray&, incomingPacket)); - } + QMetaObject::invokeMethod(&application->getAvatarManager(), "processAvatarMixerDatagram", + Q_ARG(const QByteArray&, incomingPacket), + Q_ARG(const QWeakPointer&, avatarMixer)); } application->_bandwidthMeter.inputStream(BandwidthMeter::AVATARS).updateValue(incomingPacket.size()); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 67eaa8782c..6ce4aedccf 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -761,12 +761,12 @@ void Menu::editPreferences() { QFormLayout* form = new QFormLayout(); layout->addLayout(form, 1); - QString faceURLString = applicationInstance->getProfile()->getFaceModelURL().toString(); + QString faceURLString = applicationInstance->getAvatar()->getHead().getFaceModel().getURL().toString(); QLineEdit* faceURLEdit = new QLineEdit(faceURLString); faceURLEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH); form->addRow("Face URL:", faceURLEdit); - QString skeletonURLString = applicationInstance->getProfile()->getSkeletonModelURL().toString(); + QString skeletonURLString = applicationInstance->getAvatar()->getSkeletonModel().getURL().toString(); QLineEdit* skeletonURLEdit = new QLineEdit(skeletonURLString); skeletonURLEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH); form->addRow("Skeleton URL:", skeletonURLEdit); @@ -827,27 +827,25 @@ void Menu::editPreferences() { int ret = dialog.exec(); if (ret == QDialog::Accepted) { QUrl faceModelURL(faceURLEdit->text()); + + bool shouldDispatchIdentityPacket = false; if (faceModelURL.toString() != faceURLString) { // change the faceModelURL in the profile, it will also update this user's BlendFace - applicationInstance->getProfile()->setFaceModelURL(faceModelURL); - - // send the new face mesh URL to the data-server (if we have a client UUID) - DataServerClient::putValueForKeyAndUserString(DataServerKey::FaceMeshURL, - faceModelURL.toString().toLocal8Bit().constData(), - applicationInstance->getProfile()->getUserString()); + applicationInstance->getAvatar()->getHead().getFaceModel().setURL(faceModelURL); + shouldDispatchIdentityPacket = true; } QUrl skeletonModelURL(skeletonURLEdit->text()); if (skeletonModelURL.toString() != skeletonURLString) { // change the skeletonModelURL in the profile, it will also update this user's Body - applicationInstance->getProfile()->setSkeletonModelURL(skeletonModelURL); - - // send the new skeleton model URL to the data-server (if we have a client UUID) - DataServerClient::putValueForKeyAndUserString(DataServerKey::SkeletonURL, - skeletonModelURL.toString().toLocal8Bit().constData(), - applicationInstance->getProfile()->getUserString()); + applicationInstance->getAvatar()->getSkeletonModel().setURL(skeletonModelURL); + shouldDispatchIdentityPacket = true; + } + + if (shouldDispatchIdentityPacket) { + applicationInstance->getAvatar()->sendIdentityPacket(); } applicationInstance->getAvatar()->getHead().setPupilDilation(pupilDilation->value() / (float)pupilDilation->maximum()); diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index d98d30cf6a..09f5acc912 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -124,47 +124,32 @@ void AvatarManager::renderAvatarFades() { } } -void AvatarManager::processDataServerResponse(const QString& userString, const QStringList& keyList, - const QStringList &valueList) { - QUuid avatarKey = QUuid(userString); - if (avatarKey == MY_AVATAR_KEY) { - // ignore updates to our own mesh - return; - } - for (int i = 0; i < keyList.size(); i++) { - if (valueList[i] != " ") { - if (keyList[i] == DataServerKey::FaceMeshURL || keyList[i] == DataServerKey::SkeletonURL) { - // mesh URL for a UUID, find avatar in our list - AvatarSharedPointer matchingAvatar = _avatarHash.value(avatarKey); - if (matchingAvatar) { - Avatar* avatar = static_cast(matchingAvatar.data()); - if (keyList[i] == DataServerKey::FaceMeshURL) { - qDebug() << "Changing mesh to" << valueList[i] << "for avatar with UUID" - << uuidStringWithoutCurlyBraces(avatarKey); - - QMetaObject::invokeMethod(&(avatar->getHead().getFaceModel()), - "setURL", Q_ARG(QUrl, QUrl(valueList[i]))); - } else if (keyList[i] == DataServerKey::SkeletonURL) { - qDebug() << "Changing skeleton to" << valueList[i] << "for avatar with UUID" - << uuidStringWithoutCurlyBraces(avatarKey.toString()); - - QMetaObject::invokeMethod(&(avatar->getSkeletonModel()), - "setURL", Q_ARG(QUrl, QUrl(valueList[i]))); - } - } - } - } - } -} + void AvatarManager::processAvatarMixerDatagram(const QByteArray& datagram, const QWeakPointer& mixerWeakPointer) { + switch (packetTypeForPacket(datagram)) { + case PacketTypeAvatarData: + processAvatarDataPacket(datagram, mixerWeakPointer); + break; + case PacketTypeAvatarIdentity: + processAvatarIdentityPacket(datagram); + break; + case PacketTypeKillAvatar: + processKillAvatar(datagram); + break; + default: + break; + } +} + +void AvatarManager::processAvatarDataPacket(const QByteArray &datagram, const QWeakPointer &mixerWeakPointer) { int bytesRead = numBytesForPacketHeader(datagram); QByteArray dummyAvatarByteArray = byteArrayWithPopluatedHeader(PacketTypeAvatarData); int numDummyHeaderBytes = dummyAvatarByteArray.size(); int numDummyHeaderBytesWithoutUUID = numDummyHeaderBytes - NUM_BYTES_RFC4122_UUID; - + // enumerate over all of the avatars in this packet // only add them if mixerWeakPointer points to something (meaning that mixer is still around) while (bytesRead < datagram.size() && mixerWeakPointer.data()) { @@ -181,10 +166,6 @@ void AvatarManager::processAvatarMixerDatagram(const QByteArray& datagram, const matchingAvatar = AvatarSharedPointer(avatar); _avatarHash.insert(nodeUUID, matchingAvatar); - // new UUID requires mesh and skeleton request to data-server - DataServerClient::getValuesForKeysAndUUID(QStringList() << DataServerKey::FaceMeshURL << DataServerKey::SkeletonURL, - nodeUUID, this); - qDebug() << "Adding avatar with UUID" << nodeUUID << "to AvatarManager hash."; } @@ -197,6 +178,42 @@ void AvatarManager::processAvatarMixerDatagram(const QByteArray& datagram, const // have the matching (or new) avatar parse the data from the packet bytesRead += matchingAvatar->parseData(dummyAvatarByteArray) - numDummyHeaderBytesWithoutUUID; } + +} + +void AvatarManager::processAvatarIdentityPacket(const QByteArray &packet) { + // setup a data stream to parse the packet + QDataStream identityStream(packet); + identityStream.skipRawData(numBytesForPacketHeader(packet)); + + QUuid nodeUUID; + + while (!identityStream.atEnd()) { + identityStream >> nodeUUID; + + // mesh URL for a UUID, find avatar in our list + AvatarSharedPointer matchingAvatar = _avatarHash.value(nodeUUID); + if (matchingAvatar) { + QUrl faceMeshURL, skeletonURL; + identityStream >> faceMeshURL >> skeletonURL; + + Avatar* avatar = static_cast(matchingAvatar.data()); + + if (avatar->getHead().getFaceModel().getURL() != faceMeshURL) { + qDebug() << "Changing mesh to" << faceMeshURL.toString() << "for avatar with UUID" + << uuidStringWithoutCurlyBraces(nodeUUID); + + avatar->getHead().getFaceModel().setURL(faceMeshURL); + } + + if (avatar->getSkeletonModel().getURL() != skeletonURL) { + qDebug() << "Changing skeleton to" << skeletonURL << "for avatar with UUID" + << uuidStringWithoutCurlyBraces(nodeUUID); + + avatar->getSkeletonModel().setURL(skeletonURL); + } + } + } } void AvatarManager::processKillAvatar(const QByteArray& datagram) { diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 6605f5c234..35dbf8dbb0 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -20,7 +20,7 @@ class MyAvatar; -class AvatarManager : public QObject, public DataServerCallbackObject, public AvatarHashMap { +class AvatarManager : public QObject, public AvatarHashMap { Q_OBJECT public: AvatarManager(QObject* parent = 0); @@ -35,13 +35,14 @@ public: void clearOtherAvatars(); public slots: - void processDataServerResponse(const QString& userString, const QStringList& keyList, const QStringList& valueList); - void processAvatarMixerDatagram(const QByteArray& datagram, const QWeakPointer& mixerWeakPointer); - void processKillAvatar(const QByteArray& datagram); - + private: AvatarManager(const AvatarManager& other); + + void processAvatarDataPacket(const QByteArray& packet, const QWeakPointer& mixerWeakPointer); + void processAvatarIdentityPacket(const QByteArray& packet); + void processKillAvatar(const QByteArray& datagram); void simulateAvatarFades(float deltaTime); void renderAvatarFades(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 0bdc5e9748..4ef0105c1d 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -641,6 +641,16 @@ void MyAvatar::sendKillAvatar() { NodeList::getInstance()->broadcastToNodes(killPacket, NodeSet() << NodeType::AvatarMixer); } +void MyAvatar::sendIdentityPacket() { + QByteArray identityPacket = byteArrayWithPopluatedHeader(PacketTypeAvatarIdentity); + QDataStream identityStream(&identityPacket, QIODevice::Append); + + identityStream << _head.getFaceModel().getURL(); + identityStream << _skeletonModel.getURL(); + + NodeList::getInstance()->broadcastToNodes(identityPacket, NodeSet() << NodeType::AvatarMixer); +} + void MyAvatar::orbit(const glm::vec3& position, int deltaX, int deltaY) { // first orbit horizontally glm::quat orientation = getOrientation(); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index c3ef1e4bfb..7dfb8812dd 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -94,6 +94,8 @@ public slots: void increaseSize(); void decreaseSize(); void resetSize(); + + void sendIdentityPacket(); private: bool _mousePressed; diff --git a/interface/src/avatar/Profile.cpp b/interface/src/avatar/Profile.cpp index 902a0ea12a..7f9ae123dc 100644 --- a/interface/src/avatar/Profile.cpp +++ b/interface/src/avatar/Profile.cpp @@ -20,17 +20,13 @@ Profile::Profile(const QString &username) : _uuid(), _lastDomain(), _lastPosition(0.0, 0.0, 0.0), - _lastOrientationSend(0), - _faceModelURL(), - _skeletonModelURL() + _lastOrientationSend(0) { if (!username.isEmpty()) { setUsername(username); // we've been given a new username, ask the data-server for profile DataServerClient::getValueForKeyAndUserString(DataServerKey::UUID, getUserString(), this); - DataServerClient::getValueForKeyAndUserString(DataServerKey::FaceMeshURL, getUserString(), this); - DataServerClient::getValueForKeyAndUserString(DataServerKey::SkeletonURL, getUserString(), this); // send our current domain server to the data-server updateDomain(NodeList::getInstance()->getDomainHostname()); @@ -59,20 +55,6 @@ void Profile::setUUID(const QUuid& uuid) { } } -void Profile::setFaceModelURL(const QUrl& faceModelURL) { - _faceModelURL = faceModelURL; - - QMetaObject::invokeMethod(&Application::getInstance()->getAvatar()->getHead().getFaceModel(), - "setURL", Q_ARG(QUrl, _faceModelURL)); -} - -void Profile::setSkeletonModelURL(const QUrl& skeletonModelURL) { - _skeletonModelURL = skeletonModelURL; - - QMetaObject::invokeMethod(&Application::getInstance()->getAvatar()->getSkeletonModel(), - "setURL", Q_ARG(QUrl, _skeletonModelURL)); -} - void Profile::updateDomain(const QString& domain) { if (_lastDomain != domain) { _lastDomain = domain; @@ -137,8 +119,6 @@ void Profile::saveData(QSettings* settings) { settings->setValue("username", _username); settings->setValue("UUID", _uuid); - settings->setValue("faceModelURL", _faceModelURL); - settings->setValue("skeletonModelURL", _skeletonModelURL); settings->endGroup(); } @@ -148,8 +128,6 @@ void Profile::loadData(QSettings* settings) { setUsername(settings->value("username").toString()); this->setUUID(settings->value("UUID").toUuid()); - _faceModelURL = settings->value("faceModelURL").toUrl(); - _skeletonModelURL = settings->value("skeletonModelURL").toUrl(); settings->endGroup(); } @@ -157,17 +135,7 @@ void Profile::loadData(QSettings* settings) { void Profile::processDataServerResponse(const QString& userString, const QStringList& keyList, const QStringList& valueList) { for (int i = 0; i < keyList.size(); i++) { if (valueList[i] != " ") { - if (keyList[i] == DataServerKey::FaceMeshURL) { - if (userString == _username || userString == uuidStringWithoutCurlyBraces(_uuid)) { - qDebug("Changing user's face model URL to %s", valueList[i].toLocal8Bit().constData()); - Application::getInstance()->getProfile()->setFaceModelURL(QUrl(valueList[i])); - } - } else if (keyList[i] == DataServerKey::SkeletonURL) { - if (userString == _username || userString == uuidStringWithoutCurlyBraces(_uuid)) { - qDebug("Changing user's skeleton URL to %s", valueList[i].toLocal8Bit().constData()); - Application::getInstance()->getProfile()->setSkeletonModelURL(QUrl(valueList[i])); - } - } else if (keyList[i] == DataServerKey::Domain && keyList[i + 1] == DataServerKey::Position && + if (keyList[i] == DataServerKey::Domain && keyList[i + 1] == DataServerKey::Position && keyList[i + 2] == DataServerKey::Orientation && valueList[i] != " " && valueList[i + 1] != " " && valueList[i + 2] != " ") { diff --git a/interface/src/avatar/Profile.h b/interface/src/avatar/Profile.h index 5cb2295f5b..8a0c021ed6 100644 --- a/interface/src/avatar/Profile.h +++ b/interface/src/avatar/Profile.h @@ -31,12 +31,6 @@ public: void setUUID(const QUuid& uuid); const QUuid& getUUID() { return _uuid; } - void setFaceModelURL(const QUrl& faceModelURL); - const QUrl& getFaceModelURL() const { return _faceModelURL; } - - void setSkeletonModelURL(const QUrl& skeletonModelURL); - const QUrl& getSkeletonModelURL() const { return _skeletonModelURL; } - void updateDomain(const QString& domain); void updatePosition(const glm::vec3 position); void updateOrientation(const glm::quat& orientation); @@ -58,8 +52,6 @@ private: glm::vec3 _lastPosition; glm::vec3 _lastOrientation; quint64 _lastOrientationSend; - QUrl _faceModelURL; - QUrl _skeletonModelURL; }; #endif /* defined(__hifi__Profile__) */ diff --git a/libraries/shared/src/DataServerClient.h b/libraries/shared/src/DataServerClient.h index 0360576645..aac3150679 100644 --- a/libraries/shared/src/DataServerClient.h +++ b/libraries/shared/src/DataServerClient.h @@ -52,8 +52,6 @@ private: namespace DataServerKey { const QString Domain = "domain"; - const QString FaceMeshURL = "mesh"; - const QString SkeletonURL = "skeleton"; const QString Position = "position"; const QString Orientation = "orientation"; const QString UUID = "uuid"; diff --git a/libraries/shared/src/PacketHeaders.h b/libraries/shared/src/PacketHeaders.h index 543dce0504..48d5175bd6 100644 --- a/libraries/shared/src/PacketHeaders.h +++ b/libraries/shared/src/PacketHeaders.h @@ -51,7 +51,8 @@ enum PacketType { PacketTypeParticleAddOrEdit, PacketTypeParticleErase, PacketTypeParticleAddResponse, - PacketTypeMetavoxelData + PacketTypeMetavoxelData, + PacketTypeAvatarIdentity }; typedef char PacketVersion; From e879a7f18d3dee95e23c3c9514287ee114f91a74 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 4 Feb 2014 13:04:51 -0800 Subject: [PATCH 02/42] remove some extra spacing --- interface/src/avatar/AvatarManager.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 09f5acc912..b795c84e12 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -124,8 +124,6 @@ void AvatarManager::renderAvatarFades() { } } - - void AvatarManager::processAvatarMixerDatagram(const QByteArray& datagram, const QWeakPointer& mixerWeakPointer) { switch (packetTypeForPacket(datagram)) { From 31bd5f7ce859c90b568db63f59228891f0b3940d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 4 Feb 2014 13:27:05 -0800 Subject: [PATCH 03/42] add parsing of PacketTypeAvatarIdentity to AvatarMixer --- assignment-client/src/avatars/AvatarMixer.cpp | 18 +++++++++-- .../src/avatars/AvatarMixerClientData.cpp | 25 ++++++++++++++++ .../src/avatars/AvatarMixerClientData.h | 30 +++++++++++++++++++ 3 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 assignment-client/src/avatars/AvatarMixerClientData.cpp create mode 100644 assignment-client/src/avatars/AvatarMixerClientData.h diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 358e507fc4..f15b2ff3c5 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -19,7 +19,7 @@ #include #include -#include "AvatarData.h" +#include "AvatarMixerClientData.h" #include "AvatarMixer.h" @@ -36,7 +36,7 @@ AvatarMixer::AvatarMixer(const QByteArray& packet) : void attachAvatarDataToNode(Node* newNode) { if (newNode->getLinkedData() == NULL) { - newNode->setLinkedData(new AvatarData()); + newNode->setLinkedData(new AvatarMixerClientData()); } } @@ -130,6 +130,18 @@ void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSoc } break; } + case PacketTypeAvatarIdentity: { + QUuid nodeUUID; + deconstructPacketHeader(dataByteArray, nodeUUID); + + // check if we have a matching node in our list + SharedNodePointer avatarNode = nodeList->nodeWithUUID(nodeUUID); + + if (avatarNode) { + // process the avatar identity packet sent from the avatar + reinterpret_cast(avatarNode->getLinkedData())->parseIdentityPacket(dataByteArray); + } + } case PacketTypeKillAvatar: { nodeList->processKillNode(dataByteArray); break; @@ -155,6 +167,8 @@ void AvatarMixer::run() { gettimeofday(&startTime, NULL); + + while (!_isFinished) { QCoreApplication::processEvents(); diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp new file mode 100644 index 0000000000..24e90cfcc1 --- /dev/null +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -0,0 +1,25 @@ +// +// AvatarMixerClientData.cpp +// hifi +// +// Created by Stephen Birarda on 2/4/2014. +// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. +// + +#include "AvatarMixerClientData.h" + +void AvatarMixerClientData::parseIdentityPacket(const QByteArray &packet) { + QDataStream packetStream(packet); + packetStream.skipRawData(numBytesForPacketHeader(packet)); + + QUrl faceModelURL, skeletonURL; + packetStream >> faceModelURL >> skeletonURL; + + if (faceModelURL != _faceModelURL) { + _faceModelURL = faceModelURL; + } + + if (skeletonURL != _skeletonURL) { + _skeletonURL = skeletonURL; + } +} \ No newline at end of file diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h new file mode 100644 index 0000000000..fc0511af69 --- /dev/null +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -0,0 +1,30 @@ +// +// AvatarMixerClientData.h +// hifi +// +// Created by Stephen Birarda on 2/4/2014. +// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. +// + +#ifndef __hifi__AvatarMixerClientData__ +#define __hifi__AvatarMixerClientData__ + +#include + +#include + +class AvatarMixerClientData : public AvatarData { +public: + const QUrl& getFaceModelURL() const { return _faceModelURL; } + void setFaceModelURL(const QUrl& faceModelURL) { _faceModelURL = faceModelURL; } + + const QUrl& getSkeletonURL() const { return _skeletonURL; } + void setSkeletonURL(const QUrl& skeletonURL) { _skeletonURL = skeletonURL; } + + void parseIdentityPacket(const QByteArray& packet); +private: + QUrl _faceModelURL; + QUrl _skeletonURL; +}; + +#endif /* defined(__hifi__AvatarMixerClientData__) */ From 33305ad111357bf687578fe0a34e0ea5d7a9de6a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 4 Feb 2014 13:42:22 -0800 Subject: [PATCH 04/42] have the avatar-mixer broadcast identity packets every 5 seconds --- assignment-client/src/avatars/AvatarMixer.cpp | 53 ++++++++++++++++--- .../src/avatars/AvatarMixerClientData.cpp | 7 +++ .../src/avatars/AvatarMixerClientData.h | 2 + 3 files changed, 54 insertions(+), 8 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index f15b2ff3c5..1141f2cf5c 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -11,6 +11,7 @@ // nodes, and broadcasts that data back to them, every BROADCAST_INTERVAL ms. #include +#include #include #include @@ -50,9 +51,7 @@ void attachAvatarDataToNode(Node* newNode) { void broadcastAvatarData() { static QByteArray mixedAvatarByteArray; - int numPacketHeaderBytes = populatePacketHeader(mixedAvatarByteArray, PacketTypeBulkAvatarData); - - int packetsSent = 0; + static int numPacketHeaderBytes = populatePacketHeader(mixedAvatarByteArray, PacketTypeBulkAvatarData); NodeList* nodeList = NodeList::getInstance(); @@ -74,8 +73,6 @@ void broadcastAvatarData() { avatarByteArray.append(nodeData->toByteArray()); if (avatarByteArray.size() + mixedAvatarByteArray.size() > MAX_PACKET_SIZE) { - packetsSent++; - //printf("packetsSent=%d packetLength=%d\n", packetsSent, packetLength); nodeList->getNodeSocket().writeDatagram(mixedAvatarByteArray, node->getActiveSocket()->getAddress(), node->getActiveSocket()->getPort()); @@ -89,8 +86,6 @@ void broadcastAvatarData() { } } - packetsSent++; - //printf("packetsSent=%d packetLength=%d\n", packetsSent, packetLength); nodeList->getNodeSocket().writeDatagram(mixedAvatarByteArray, node->getActiveSocket()->getAddress(), node->getActiveSocket()->getPort()); @@ -98,6 +93,37 @@ void broadcastAvatarData() { } } +void broadcastIdentityPacket() { + + NodeList* nodeList = NodeList::getInstance(); + + QByteArray avatarIdentityPacket = byteArrayWithPopluatedHeader(PacketTypeAvatarIdentity); + int numPacketHeaderBytes = avatarIdentityPacket.size(); + + foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { + if (node->getLinkedData() && node->getType() == NodeType::Agent) { + QByteArray individualData; + QDataStream individualDataStream(&individualData, QIODevice::Append); + + AvatarMixerClientData* nodeData = reinterpret_cast(node->getLinkedData()); + + individualDataStream << node->getUUID() << nodeData->getFaceModelURL() << nodeData->getSkeletonURL(); + + if (avatarIdentityPacket.size() + individualData.size() > MAX_PACKET_SIZE) { + // we've hit MTU, send out the current packet before appending + nodeList->broadcastToNodes(avatarIdentityPacket, NodeSet() << NodeType::Agent); + avatarIdentityPacket.resize(numPacketHeaderBytes); + } + + // append the individual data to the current the avatarIdentityPacket + avatarIdentityPacket.append(individualData); + } + } + + // send out the final packet + nodeList->broadcastToNodes(avatarIdentityPacket, NodeSet() << NodeType::Agent); +} + void AvatarMixer::nodeKilled(SharedNodePointer killedNode) { if (killedNode->getType() == NodeType::Agent && killedNode->getLinkedData()) { @@ -154,6 +180,8 @@ void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSoc } +const qint64 AVATAR_IDENTITY_KEYFRAME_MSECS = 5000; + void AvatarMixer::run() { commonInit(AVATAR_MIXER_LOGGING_NAME, NodeType::AvatarMixer); @@ -167,7 +195,8 @@ void AvatarMixer::run() { gettimeofday(&startTime, NULL); - + QElapsedTimer identityTimer; + identityTimer.start(); while (!_isFinished) { @@ -179,6 +208,14 @@ void AvatarMixer::run() { broadcastAvatarData(); + if (identityTimer.elapsed() >= AVATAR_IDENTITY_KEYFRAME_MSECS) { + // it's time to broadcast the keyframe identity packets + broadcastIdentityPacket(); + + // restart the timer so we do it again in AVATAR_IDENTITY_KEYFRAME_MSECS + identityTimer.restart(); + } + int usecToSleep = usecTimestamp(&startTime) + (++nextFrame * AVATAR_DATA_SEND_INTERVAL_USECS) - usecTimestampNow(); if (usecToSleep > 0) { diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index 24e90cfcc1..d7a0cd1aa4 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -8,6 +8,13 @@ #include "AvatarMixerClientData.h" +AvatarMixerClientData::AvatarMixerClientData() : + _faceModelURL(), + _skeletonURL() +{ + +} + void AvatarMixerClientData::parseIdentityPacket(const QByteArray &packet) { QDataStream packetStream(packet); packetStream.skipRawData(numBytesForPacketHeader(packet)); diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index fc0511af69..3fd2f6a20e 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -15,6 +15,8 @@ class AvatarMixerClientData : public AvatarData { public: + AvatarMixerClientData(); + const QUrl& getFaceModelURL() const { return _faceModelURL; } void setFaceModelURL(const QUrl& faceModelURL) { _faceModelURL = faceModelURL; } From 06a3da2b2522b38441d22733c9577c285ee1a9bd Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 4 Feb 2014 14:06:08 -0800 Subject: [PATCH 05/42] store and load face/skeleton meshes in local settings --- interface/src/avatar/MyAvatar.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 4ef0105c1d..327fb860f1 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -608,6 +608,9 @@ void MyAvatar::saveData(QSettings* settings) { settings->setValue("leanScale", _leanScale); settings->setValue("scale", _targetScale); + + settings->setValue("faceModelURL", _head.getFaceModel().getURL()); + settings->setValue("skeletonURL", _skeletonModel.getURL()); settings->endGroup(); } @@ -632,6 +635,9 @@ void MyAvatar::loadData(QSettings* settings) { _targetScale = loadSetting(settings, "scale", 1.0f); setScale(_scale); Application::getInstance()->getCamera()->setScale(_scale); + + _head.getFaceModel().setURL(settings->value("faceModelURL").toUrl()); + _skeletonModel.setURL(settings->value("skeletonURL").toUrl()); settings->endGroup(); } From 26c961dc66b393e04f8cbedc98e801aef6f5276b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 4 Feb 2014 14:24:08 -0800 Subject: [PATCH 06/42] send identity packets when changes occur between keyframes --- assignment-client/src/avatars/AvatarMixer.cpp | 14 +++++++++++--- assignment-client/src/avatars/AvatarMixer.h | 1 + .../src/avatars/AvatarMixerClientData.cpp | 8 +++++++- .../src/avatars/AvatarMixerClientData.h | 6 +++++- interface/src/Application.cpp | 10 +++++++++- interface/src/Application.h | 1 + 6 files changed, 34 insertions(+), 6 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 1141f2cf5c..c345ce3c81 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -117,6 +117,9 @@ void broadcastIdentityPacket() { // append the individual data to the current the avatarIdentityPacket avatarIdentityPacket.append(individualData); + + // re-set the bool in AvatarMixerClientData so a change between key frames gets sent out + nodeData->setHasSentPacketBetweenKeyFrames(false); } } @@ -163,9 +166,14 @@ void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSoc // check if we have a matching node in our list SharedNodePointer avatarNode = nodeList->nodeWithUUID(nodeUUID); - if (avatarNode) { - // process the avatar identity packet sent from the avatar - reinterpret_cast(avatarNode->getLinkedData())->parseIdentityPacket(dataByteArray); + if (avatarNode && avatarNode->getLinkedData()) { + AvatarMixerClientData* nodeData = reinterpret_cast(avatarNode->getLinkedData()); + if (nodeData->shouldSendIdentityPacketAfterParsing(dataByteArray)) { + // this avatar changed their identity in some way and we haven't sent a packet in this keyframe + QByteArray identityPacket = byteArrayWithPopluatedHeader(PacketTypeAvatarIdentity); + QDataStream identityStream(&identityPacket, QIODevice::Append); + identityStream << avatarNode->getUUID() << nodeData->getFaceModelURL() << nodeData->getSkeletonURL(); + } } } case PacketTypeKillAvatar: { diff --git a/assignment-client/src/avatars/AvatarMixer.h b/assignment-client/src/avatars/AvatarMixer.h index 92ab1a5c53..61141411e6 100644 --- a/assignment-client/src/avatars/AvatarMixer.h +++ b/assignment-client/src/avatars/AvatarMixer.h @@ -20,6 +20,7 @@ public slots: /// runs the avatar mixer void run(); + void nodeAdded(SharedNodePointer nodeAdded); void nodeKilled(SharedNodePointer killedNode); void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr); diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index d7a0cd1aa4..26339c2d9e 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -15,18 +15,24 @@ AvatarMixerClientData::AvatarMixerClientData() : } -void AvatarMixerClientData::parseIdentityPacket(const QByteArray &packet) { +bool AvatarMixerClientData::shouldSendIdentityPacketAfterParsing(const QByteArray &packet) { QDataStream packetStream(packet); packetStream.skipRawData(numBytesForPacketHeader(packet)); QUrl faceModelURL, skeletonURL; packetStream >> faceModelURL >> skeletonURL; + bool hasIdentityChanged = false; + if (faceModelURL != _faceModelURL) { _faceModelURL = faceModelURL; + hasIdentityChanged = true; } if (skeletonURL != _skeletonURL) { _skeletonURL = skeletonURL; + hasIdentityChanged = true; } + + return hasIdentityChanged && !_hasSentPacketBetweenKeyFrames; } \ No newline at end of file diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index 3fd2f6a20e..813bf3d464 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -23,10 +23,14 @@ public: const QUrl& getSkeletonURL() const { return _skeletonURL; } void setSkeletonURL(const QUrl& skeletonURL) { _skeletonURL = skeletonURL; } - void parseIdentityPacket(const QByteArray& packet); + void setHasSentPacketBetweenKeyFrames(bool hasSentPacketBetweenKeyFrames) + { _hasSentPacketBetweenKeyFrames = hasSentPacketBetweenKeyFrames; } + + bool shouldSendIdentityPacketAfterParsing(const QByteArray& packet); private: QUrl _faceModelURL; QUrl _skeletonURL; + bool _hasSentPacketBetweenKeyFrames; }; #endif /* defined(__hifi__AvatarMixerClientData__) */ diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 886d44c1fb..3537b66478 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -199,7 +199,8 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : audioThread->start(); connect(nodeList, SIGNAL(domainChanged(const QString&)), SLOT(domainChanged(const QString&))); - + connect(nodeList, &NodeList::nodeAdded, this, &Application::nodeAdded); + connect(nodeList, &NodeList::nodeKilled, this, &Application::nodeKilled); connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer))); connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), &_voxels, SLOT(nodeAdded(SharedNodePointer))); connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), &_voxels, SLOT(nodeKilled(SharedNodePointer))); @@ -3885,6 +3886,13 @@ void Application::domainChanged(const QString& domainHostname) { updateLocalOctreeCache(); } +void Application::nodeAdded(SharedNodePointer node) { + if (node->getType() == NodeType::AvatarMixer) { + // new avatar mixer, send off our identity packet right away + _myAvatar->sendIdentityPacket(); + } +} + void Application::nodeKilled(SharedNodePointer node) { if (node->getType() == NodeType::VoxelServer) { QUuid nodeUUID = node->getUUID(); diff --git a/interface/src/Application.h b/interface/src/Application.h index bf9981a160..352b27de46 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -213,6 +213,7 @@ signals: public slots: void domainChanged(const QString& domainHostname); + void nodeAdded(SharedNodePointer node); void nodeKilled(SharedNodePointer node); void packetSent(quint64 length); From 2b80a5fbb85bf2afb303a7eb04cca213d95b6621 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 4 Feb 2014 14:40:41 -0800 Subject: [PATCH 07/42] move face/skeleton model URLs to AvatarData --- assignment-client/src/avatars/AvatarMixer.cpp | 15 ++++----- .../src/avatars/AvatarMixerClientData.cpp | 25 +-------------- .../src/avatars/AvatarMixerClientData.h | 18 +++-------- interface/src/avatar/Avatar.cpp | 10 ++++++ interface/src/avatar/Avatar.h | 5 ++- interface/src/avatar/MyAvatar.cpp | 13 +++----- libraries/avatars/src/AvatarData.cpp | 32 +++++++++++++++++++ libraries/avatars/src/AvatarData.h | 11 +++++++ 8 files changed, 75 insertions(+), 54 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index c345ce3c81..e6a73c7f02 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -102,12 +102,10 @@ void broadcastIdentityPacket() { foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { if (node->getLinkedData() && node->getType() == NodeType::Agent) { - QByteArray individualData; - QDataStream individualDataStream(&individualData, QIODevice::Append); AvatarMixerClientData* nodeData = reinterpret_cast(node->getLinkedData()); - - individualDataStream << node->getUUID() << nodeData->getFaceModelURL() << nodeData->getSkeletonURL(); + QByteArray individualData = nodeData->identityByteArray(); + individualData.replace(0, NUM_BYTES_RFC4122_UUID, node->getUUID().toRfc4122()); if (avatarIdentityPacket.size() + individualData.size() > MAX_PACKET_SIZE) { // we've hit MTU, send out the current packet before appending @@ -119,7 +117,7 @@ void broadcastIdentityPacket() { avatarIdentityPacket.append(individualData); // re-set the bool in AvatarMixerClientData so a change between key frames gets sent out - nodeData->setHasSentPacketBetweenKeyFrames(false); + nodeData->setHasSentIdentityBetweenKeyFrames(false); } } @@ -168,11 +166,12 @@ void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSoc if (avatarNode && avatarNode->getLinkedData()) { AvatarMixerClientData* nodeData = reinterpret_cast(avatarNode->getLinkedData()); - if (nodeData->shouldSendIdentityPacketAfterParsing(dataByteArray)) { + if (nodeData->hasIdentityChangedAfterParsing(dataByteArray) + && !nodeData->hasSentIdentityBetweenKeyFrames()) { // this avatar changed their identity in some way and we haven't sent a packet in this keyframe QByteArray identityPacket = byteArrayWithPopluatedHeader(PacketTypeAvatarIdentity); - QDataStream identityStream(&identityPacket, QIODevice::Append); - identityStream << avatarNode->getUUID() << nodeData->getFaceModelURL() << nodeData->getSkeletonURL(); + identityPacket.append(nodeData->identityByteArray()); + nodeList->broadcastToNodes(identityPacket, NodeSet() << NodeType::Agent); } } } diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index 26339c2d9e..0261613532 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -9,30 +9,7 @@ #include "AvatarMixerClientData.h" AvatarMixerClientData::AvatarMixerClientData() : - _faceModelURL(), - _skeletonURL() + _hasSentIdentityBetweenKeyFrames(false) { } - -bool AvatarMixerClientData::shouldSendIdentityPacketAfterParsing(const QByteArray &packet) { - QDataStream packetStream(packet); - packetStream.skipRawData(numBytesForPacketHeader(packet)); - - QUrl faceModelURL, skeletonURL; - packetStream >> faceModelURL >> skeletonURL; - - bool hasIdentityChanged = false; - - if (faceModelURL != _faceModelURL) { - _faceModelURL = faceModelURL; - hasIdentityChanged = true; - } - - if (skeletonURL != _skeletonURL) { - _skeletonURL = skeletonURL; - hasIdentityChanged = true; - } - - return hasIdentityChanged && !_hasSentPacketBetweenKeyFrames; -} \ No newline at end of file diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index 813bf3d464..5d4f06115f 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -17,20 +17,12 @@ class AvatarMixerClientData : public AvatarData { public: AvatarMixerClientData(); - const QUrl& getFaceModelURL() const { return _faceModelURL; } - void setFaceModelURL(const QUrl& faceModelURL) { _faceModelURL = faceModelURL; } - - const QUrl& getSkeletonURL() const { return _skeletonURL; } - void setSkeletonURL(const QUrl& skeletonURL) { _skeletonURL = skeletonURL; } - - void setHasSentPacketBetweenKeyFrames(bool hasSentPacketBetweenKeyFrames) - { _hasSentPacketBetweenKeyFrames = hasSentPacketBetweenKeyFrames; } - - bool shouldSendIdentityPacketAfterParsing(const QByteArray& packet); + bool hasSentIdentityBetweenKeyFrames() const { return _hasSentIdentityBetweenKeyFrames; } + void setHasSentIdentityBetweenKeyFrames(bool hasSentIdentityBetweenKeyFrames) + { _hasSentIdentityBetweenKeyFrames = hasSentIdentityBetweenKeyFrames; } private: - QUrl _faceModelURL; - QUrl _skeletonURL; - bool _hasSentPacketBetweenKeyFrames; + + bool _hasSentIdentityBetweenKeyFrames; }; #endif /* defined(__hifi__AvatarMixerClientData__) */ diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 4b4c189729..ceb1cecca5 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -334,6 +334,16 @@ bool Avatar::findSphereCollision(const glm::vec3& sphereCenter, float sphereRadi return false; } +void Avatar::setFaceModelURL(const QUrl &faceModelURL) { + _faceModelURL = faceModelURL; + _head.getFaceModel().setURL(faceModelURL); +} + +void Avatar::setSkeletonURL(const QUrl &skeletonURL) { + _skeletonURL = skeletonURL; + _skeletonModel.setURL(skeletonURL); +} + int Avatar::parseData(const QByteArray& packet) { // change in position implies movement glm::vec3 oldPosition = _position; diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 61b36706d2..a5312e1b7a 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -112,7 +112,10 @@ public: virtual bool findSphereCollision(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision); virtual bool isMyAvatar() { return false; } - + + virtual void setFaceModelURL(const QUrl& faceModelURL); + virtual void setSkeletonURL(const QUrl& skeletonURL); + int parseData(const QByteArray& packet); static void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 327fb860f1..30de974ab0 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -609,8 +609,8 @@ void MyAvatar::saveData(QSettings* settings) { settings->setValue("leanScale", _leanScale); settings->setValue("scale", _targetScale); - settings->setValue("faceModelURL", _head.getFaceModel().getURL()); - settings->setValue("skeletonURL", _skeletonModel.getURL()); + settings->setValue("faceModelURL", _faceModelURL); + settings->setValue("skeletonURL", _skeletonURL); settings->endGroup(); } @@ -636,8 +636,8 @@ void MyAvatar::loadData(QSettings* settings) { setScale(_scale); Application::getInstance()->getCamera()->setScale(_scale); - _head.getFaceModel().setURL(settings->value("faceModelURL").toUrl()); - _skeletonModel.setURL(settings->value("skeletonURL").toUrl()); + setFaceModelURL(settings->value("faceModelURL").toUrl()); + setSkeletonURL(settings->value("skeletonURL").toUrl()); settings->endGroup(); } @@ -649,10 +649,7 @@ void MyAvatar::sendKillAvatar() { void MyAvatar::sendIdentityPacket() { QByteArray identityPacket = byteArrayWithPopluatedHeader(PacketTypeAvatarIdentity); - QDataStream identityStream(&identityPacket, QIODevice::Append); - - identityStream << _head.getFaceModel().getURL(); - identityStream << _skeletonModel.getURL(); + identityPacket.append(AvatarData::identityByteArray()); NodeList::getInstance()->broadcastToNodes(identityPacket, NodeSet() << NodeType::AvatarMixer); } diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 98afa76107..7f7fef9c9e 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -270,6 +270,38 @@ int AvatarData::parseData(const QByteArray& packet) { return sourceBuffer - startPosition; } +bool AvatarData::hasIdentityChangedAfterParsing(const QByteArray &packet) { + QDataStream packetStream(packet); + packetStream.skipRawData(numBytesForPacketHeader(packet)); + + QUuid avatarUUID; + QUrl faceModelURL, skeletonURL; + packetStream >> avatarUUID >> faceModelURL >> skeletonURL; + + bool hasIdentityChanged = false; + + if (faceModelURL != _faceModelURL) { + setFaceModelURL(faceModelURL); + hasIdentityChanged = true; + } + + if (skeletonURL != _skeletonURL) { + setSkeletonURL(skeletonURL); + hasIdentityChanged = true; + } + + return hasIdentityChanged; +} + +QByteArray AvatarData::identityByteArray() { + QByteArray identityData; + QDataStream identityStream(&identityData, QIODevice::Append); + + identityStream << QUuid() << _faceModelURL << _skeletonURL; + + return identityData; +} + void AvatarData::setClampedTargetScale(float targetScale) { targetScale = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 0869445090..7cb5dc835f 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -30,6 +30,7 @@ typedef unsigned long long quint64; #include #include +#include #include #include @@ -142,6 +143,14 @@ public: return false; } + bool hasIdentityChangedAfterParsing(const QByteArray& packet); + QByteArray identityByteArray(); + + const QUrl& getFaceModelURL() const { return _faceModelURL; } + const QUrl& getSkeletonURL() const { return _skeletonURL; } + virtual void setFaceModelURL(const QUrl& faceModelURL) { _faceModelURL = faceModelURL; } + virtual void setSkeletonURL(const QUrl& skeletonURL) { _skeletonURL = skeletonURL; } + protected: glm::vec3 _position; glm::vec3 _handPosition; @@ -168,6 +177,8 @@ protected: HeadData* _headData; HandData* _handData; + QUrl _faceModelURL; + QUrl _skeletonURL; private: // privatize the copy constructor and assignment operator so they cannot be called AvatarData(const AvatarData&); From 3959209bc2a1830c73d764ca0ab7e806b2bf0b3c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 4 Feb 2014 14:49:56 -0800 Subject: [PATCH 08/42] complete movement of URLs to AvatarData for re-usability --- assignment-client/src/avatars/AvatarMixer.cpp | 2 ++ interface/src/Menu.cpp | 4 ++-- interface/src/avatar/Avatar.cpp | 6 +++--- interface/src/avatar/MyAvatar.cpp | 4 ++-- libraries/avatars/src/AvatarData.cpp | 10 +++++----- libraries/avatars/src/AvatarData.h | 6 +++--- 6 files changed, 17 insertions(+), 15 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index e6a73c7f02..12d5bc926f 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -171,6 +171,8 @@ void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSoc // this avatar changed their identity in some way and we haven't sent a packet in this keyframe QByteArray identityPacket = byteArrayWithPopluatedHeader(PacketTypeAvatarIdentity); identityPacket.append(nodeData->identityByteArray()); + + nodeData->setHasSentIdentityBetweenKeyFrames(true); nodeList->broadcastToNodes(identityPacket, NodeSet() << NodeType::Agent); } } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6ce4aedccf..505c799e63 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -832,7 +832,7 @@ void Menu::editPreferences() { if (faceModelURL.toString() != faceURLString) { // change the faceModelURL in the profile, it will also update this user's BlendFace - applicationInstance->getAvatar()->getHead().getFaceModel().setURL(faceModelURL); + applicationInstance->getAvatar()->setFaceModelURL(faceModelURL); shouldDispatchIdentityPacket = true; } @@ -840,7 +840,7 @@ void Menu::editPreferences() { if (skeletonModelURL.toString() != skeletonURLString) { // change the skeletonModelURL in the profile, it will also update this user's Body - applicationInstance->getAvatar()->getSkeletonModel().setURL(skeletonModelURL); + applicationInstance->getAvatar()->setSkeletonURL(skeletonModelURL); shouldDispatchIdentityPacket = true; } diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index ceb1cecca5..47bdcf017b 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -339,9 +339,9 @@ void Avatar::setFaceModelURL(const QUrl &faceModelURL) { _head.getFaceModel().setURL(faceModelURL); } -void Avatar::setSkeletonURL(const QUrl &skeletonURL) { - _skeletonURL = skeletonURL; - _skeletonModel.setURL(skeletonURL); +void Avatar::setSkeletonURL(const QUrl &skeletonModelURL) { + _skeletonModelURL = skeletonModelURL; + _skeletonModel.setURL(skeletonModelURL); } int Avatar::parseData(const QByteArray& packet) { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 30de974ab0..ef7a8e6019 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -610,7 +610,7 @@ void MyAvatar::saveData(QSettings* settings) { settings->setValue("scale", _targetScale); settings->setValue("faceModelURL", _faceModelURL); - settings->setValue("skeletonURL", _skeletonURL); + settings->setValue("skeletonModelURL", _skeletonModelURL); settings->endGroup(); } @@ -637,7 +637,7 @@ void MyAvatar::loadData(QSettings* settings) { Application::getInstance()->getCamera()->setScale(_scale); setFaceModelURL(settings->value("faceModelURL").toUrl()); - setSkeletonURL(settings->value("skeletonURL").toUrl()); + setSkeletonURL(settings->value("skeletonModelURL").toUrl()); settings->endGroup(); } diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 7f7fef9c9e..ae765f71a7 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -275,8 +275,8 @@ bool AvatarData::hasIdentityChangedAfterParsing(const QByteArray &packet) { packetStream.skipRawData(numBytesForPacketHeader(packet)); QUuid avatarUUID; - QUrl faceModelURL, skeletonURL; - packetStream >> avatarUUID >> faceModelURL >> skeletonURL; + QUrl faceModelURL, skeletonModelURL; + packetStream >> avatarUUID >> faceModelURL >> skeletonModelURL; bool hasIdentityChanged = false; @@ -285,8 +285,8 @@ bool AvatarData::hasIdentityChangedAfterParsing(const QByteArray &packet) { hasIdentityChanged = true; } - if (skeletonURL != _skeletonURL) { - setSkeletonURL(skeletonURL); + if (skeletonModelURL != _skeletonModelURL) { + setSkeletonModelURL(skeletonModelURL); hasIdentityChanged = true; } @@ -297,7 +297,7 @@ QByteArray AvatarData::identityByteArray() { QByteArray identityData; QDataStream identityStream(&identityData, QIODevice::Append); - identityStream << QUuid() << _faceModelURL << _skeletonURL; + identityStream << QUuid() << _faceModelURL << _skeletonModelURL; return identityData; } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 7cb5dc835f..30c1f018b5 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -147,9 +147,9 @@ public: QByteArray identityByteArray(); const QUrl& getFaceModelURL() const { return _faceModelURL; } - const QUrl& getSkeletonURL() const { return _skeletonURL; } + const QUrl& getSkeletonModelURL() const { return _skeletonModelURL; } virtual void setFaceModelURL(const QUrl& faceModelURL) { _faceModelURL = faceModelURL; } - virtual void setSkeletonURL(const QUrl& skeletonURL) { _skeletonURL = skeletonURL; } + virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) { _skeletonModelURL = skeletonModelURL; } protected: glm::vec3 _position; @@ -178,7 +178,7 @@ protected: HandData* _handData; QUrl _faceModelURL; - QUrl _skeletonURL; + QUrl _skeletonModelURL; private: // privatize the copy constructor and assignment operator so they cannot be called AvatarData(const AvatarData&); From 7e3442cbd0cdec35592aacd855fa7abd9dccfdf9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 4 Feb 2014 14:57:14 -0800 Subject: [PATCH 09/42] repair to PacketType so interface parses AM packet --- assignment-client/src/avatars/AvatarMixer.cpp | 4 ++-- interface/src/avatar/AvatarManager.cpp | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 12d5bc926f..5590b73021 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -51,7 +51,7 @@ void attachAvatarDataToNode(Node* newNode) { void broadcastAvatarData() { static QByteArray mixedAvatarByteArray; - static int numPacketHeaderBytes = populatePacketHeader(mixedAvatarByteArray, PacketTypeBulkAvatarData); + int numPacketHeaderBytes = populatePacketHeader(mixedAvatarByteArray, PacketTypeBulkAvatarData); NodeList* nodeList = NodeList::getInstance(); @@ -69,7 +69,7 @@ void broadcastAvatarData() { QByteArray avatarByteArray; avatarByteArray.append(otherNode->getUUID().toRfc4122()); - AvatarData* nodeData = (AvatarData*) otherNode->getLinkedData(); + AvatarMixerClientData* nodeData = reinterpret_cast(otherNode->getLinkedData()); avatarByteArray.append(nodeData->toByteArray()); if (avatarByteArray.size() + mixedAvatarByteArray.size() > MAX_PACKET_SIZE) { diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index b795c84e12..f587e3c941 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -125,9 +125,8 @@ void AvatarManager::renderAvatarFades() { } void AvatarManager::processAvatarMixerDatagram(const QByteArray& datagram, const QWeakPointer& mixerWeakPointer) { - switch (packetTypeForPacket(datagram)) { - case PacketTypeAvatarData: + case PacketTypeBulkAvatarData: processAvatarDataPacket(datagram, mixerWeakPointer); break; case PacketTypeAvatarIdentity: From adaa36a51d781eb7436f68b69060d6f428998c5d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 4 Feb 2014 15:28:27 -0800 Subject: [PATCH 10/42] repairs to key-framed URL sending through avatar-mixer --- assignment-client/src/avatars/AvatarMixer.cpp | 10 ++++++++-- interface/src/Application.cpp | 2 +- interface/src/avatar/AvatarManager.cpp | 16 ++++++++-------- libraries/avatars/src/AvatarData.cpp | 2 ++ 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 5590b73021..ecf9bfe4b2 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -122,7 +122,9 @@ void broadcastIdentityPacket() { } // send out the final packet - nodeList->broadcastToNodes(avatarIdentityPacket, NodeSet() << NodeType::Agent); + if (avatarIdentityPacket.size() > numPacketHeaderBytes) { + nodeList->broadcastToNodes(avatarIdentityPacket, NodeSet() << NodeType::Agent); + } } void AvatarMixer::nodeKilled(SharedNodePointer killedNode) { @@ -170,7 +172,11 @@ void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSoc && !nodeData->hasSentIdentityBetweenKeyFrames()) { // this avatar changed their identity in some way and we haven't sent a packet in this keyframe QByteArray identityPacket = byteArrayWithPopluatedHeader(PacketTypeAvatarIdentity); - identityPacket.append(nodeData->identityByteArray()); + + QByteArray individualByteArray = nodeData->identityByteArray(); + individualByteArray.replace(0, NUM_BYTES_RFC4122_UUID, nodeUUID.toRfc4122()); + + identityPacket.append(individualByteArray); nodeData->setHasSentIdentityBetweenKeyFrames(true); nodeList->broadcastToNodes(identityPacket, NodeSet() << NodeType::Agent); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3537b66478..33b118f7d3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -247,7 +247,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : // send the identity packet for our avatar each second to our avatar mixer QTimer* identityPacketTimer = new QTimer(); connect(identityPacketTimer, &QTimer::timeout, _myAvatar, &MyAvatar::sendIdentityPacket); - silentNodeTimer->start(1000); + identityPacketTimer->start(1000); QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation); diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index f587e3c941..71255427f8 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -179,6 +179,7 @@ void AvatarManager::processAvatarDataPacket(const QByteArray &datagram, const QW } void AvatarManager::processAvatarIdentityPacket(const QByteArray &packet) { + qDebug() << "Processing an avatar identity packet"; // setup a data stream to parse the packet QDataStream identityStream(packet); identityStream.skipRawData(numBytesForPacketHeader(packet)); @@ -186,28 +187,27 @@ void AvatarManager::processAvatarIdentityPacket(const QByteArray &packet) { QUuid nodeUUID; while (!identityStream.atEnd()) { - identityStream >> nodeUUID; + + QUrl faceMeshURL, skeletonURL; + identityStream >> nodeUUID >> faceMeshURL >> skeletonURL; // mesh URL for a UUID, find avatar in our list AvatarSharedPointer matchingAvatar = _avatarHash.value(nodeUUID); if (matchingAvatar) { - QUrl faceMeshURL, skeletonURL; - identityStream >> faceMeshURL >> skeletonURL; - Avatar* avatar = static_cast(matchingAvatar.data()); - if (avatar->getHead().getFaceModel().getURL() != faceMeshURL) { + if (avatar->getFaceModelURL() != faceMeshURL) { qDebug() << "Changing mesh to" << faceMeshURL.toString() << "for avatar with UUID" << uuidStringWithoutCurlyBraces(nodeUUID); - avatar->getHead().getFaceModel().setURL(faceMeshURL); + avatar->setFaceModelURL(faceMeshURL); } - if (avatar->getSkeletonModel().getURL() != skeletonURL) { + if (avatar->getFaceModelURL() != skeletonURL) { qDebug() << "Changing skeleton to" << skeletonURL << "for avatar with UUID" << uuidStringWithoutCurlyBraces(nodeUUID); - avatar->getSkeletonModel().setURL(skeletonURL); + avatar->setFaceModelURL(skeletonURL); } } } diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index ae765f71a7..90e3cd7149 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -280,6 +280,8 @@ bool AvatarData::hasIdentityChangedAfterParsing(const QByteArray &packet) { bool hasIdentityChanged = false; + qDebug() << faceModelURL; + if (faceModelURL != _faceModelURL) { setFaceModelURL(faceModelURL); hasIdentityChanged = true; From 092c969e75b50e79b9c942fea505ec3d913deffb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 4 Feb 2014 15:48:31 -0800 Subject: [PATCH 11/42] more repairs to face and skeleton model passing --- interface/src/avatar/Avatar.cpp | 4 ++-- interface/src/avatar/AvatarManager.cpp | 11 ++--------- libraries/avatars/src/AvatarData.cpp | 12 ++++++++++-- libraries/avatars/src/AvatarData.h | 4 ++-- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 47bdcf017b..37acde2b93 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -335,12 +335,12 @@ bool Avatar::findSphereCollision(const glm::vec3& sphereCenter, float sphereRadi } void Avatar::setFaceModelURL(const QUrl &faceModelURL) { - _faceModelURL = faceModelURL; + AvatarData::setFaceModelURL(faceModelURL); _head.getFaceModel().setURL(faceModelURL); } void Avatar::setSkeletonURL(const QUrl &skeletonModelURL) { - _skeletonModelURL = skeletonModelURL; + AvatarData::setSkeletonModelURL(skeletonModelURL); _skeletonModel.setURL(skeletonModelURL); } diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 71255427f8..fb4ba9c10f 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -179,7 +179,6 @@ void AvatarManager::processAvatarDataPacket(const QByteArray &datagram, const QW } void AvatarManager::processAvatarIdentityPacket(const QByteArray &packet) { - qDebug() << "Processing an avatar identity packet"; // setup a data stream to parse the packet QDataStream identityStream(packet); identityStream.skipRawData(numBytesForPacketHeader(packet)); @@ -197,17 +196,11 @@ void AvatarManager::processAvatarIdentityPacket(const QByteArray &packet) { Avatar* avatar = static_cast(matchingAvatar.data()); if (avatar->getFaceModelURL() != faceMeshURL) { - qDebug() << "Changing mesh to" << faceMeshURL.toString() << "for avatar with UUID" - << uuidStringWithoutCurlyBraces(nodeUUID); - avatar->setFaceModelURL(faceMeshURL); } - if (avatar->getFaceModelURL() != skeletonURL) { - qDebug() << "Changing skeleton to" << skeletonURL << "for avatar with UUID" - << uuidStringWithoutCurlyBraces(nodeUUID); - - avatar->setFaceModelURL(skeletonURL); + if (avatar->getSkeletonModelURL() != skeletonURL) { + avatar->setSkeletonModelURL(skeletonURL); } } } diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 90e3cd7149..ca57fff587 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -280,8 +280,6 @@ bool AvatarData::hasIdentityChangedAfterParsing(const QByteArray &packet) { bool hasIdentityChanged = false; - qDebug() << faceModelURL; - if (faceModelURL != _faceModelURL) { setFaceModelURL(faceModelURL); hasIdentityChanged = true; @@ -304,6 +302,16 @@ QByteArray AvatarData::identityByteArray() { return identityData; } +void AvatarData::setFaceModelURL(const QUrl& faceModelURL) { + qDebug() << "Changing face model for avatar to" << faceModelURL.toString(); + _faceModelURL = faceModelURL; +} + +void AvatarData::setSkeletonModelURL(const QUrl& skeletonModelURL) { + qDebug() << "Changing skeleton model for avatar to" << skeletonModelURL.toString(); + _skeletonModelURL = skeletonModelURL; +} + void AvatarData::setClampedTargetScale(float targetScale) { targetScale = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 30c1f018b5..5e4f7acb2c 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -148,8 +148,8 @@ public: const QUrl& getFaceModelURL() const { return _faceModelURL; } const QUrl& getSkeletonModelURL() const { return _skeletonModelURL; } - virtual void setFaceModelURL(const QUrl& faceModelURL) { _faceModelURL = faceModelURL; } - virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) { _skeletonModelURL = skeletonModelURL; } + virtual void setFaceModelURL(const QUrl& faceModelURL); + virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); protected: glm::vec3 _position; From 53170d3fe2035164093e418b2a4f5b740e2d301f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 4 Feb 2014 16:49:21 -0800 Subject: [PATCH 12/42] fix skeleton setting on parsing of identity packet --- assignment-client/src/avatars/AvatarMixerClientData.h | 1 + interface/src/Menu.cpp | 2 +- interface/src/avatar/Avatar.cpp | 2 +- interface/src/avatar/Avatar.h | 2 +- interface/src/avatar/MyAvatar.cpp | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index 5d4f06115f..8e046d9212 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -14,6 +14,7 @@ #include class AvatarMixerClientData : public AvatarData { + Q_OBJECT public: AvatarMixerClientData(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 505c799e63..3f5af7d4c1 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -840,7 +840,7 @@ void Menu::editPreferences() { if (skeletonModelURL.toString() != skeletonURLString) { // change the skeletonModelURL in the profile, it will also update this user's Body - applicationInstance->getAvatar()->setSkeletonURL(skeletonModelURL); + applicationInstance->getAvatar()->setSkeletonModelURL(skeletonModelURL); shouldDispatchIdentityPacket = true; } diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 37acde2b93..eabe36943d 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -339,7 +339,7 @@ void Avatar::setFaceModelURL(const QUrl &faceModelURL) { _head.getFaceModel().setURL(faceModelURL); } -void Avatar::setSkeletonURL(const QUrl &skeletonModelURL) { +void Avatar::setSkeletonModelURL(const QUrl &skeletonModelURL) { AvatarData::setSkeletonModelURL(skeletonModelURL); _skeletonModel.setURL(skeletonModelURL); } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index a5312e1b7a..c9b0bcacc2 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -114,7 +114,7 @@ public: virtual bool isMyAvatar() { return false; } virtual void setFaceModelURL(const QUrl& faceModelURL); - virtual void setSkeletonURL(const QUrl& skeletonURL); + virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); int parseData(const QByteArray& packet); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index ef7a8e6019..24b2e46191 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -637,7 +637,7 @@ void MyAvatar::loadData(QSettings* settings) { Application::getInstance()->getCamera()->setScale(_scale); setFaceModelURL(settings->value("faceModelURL").toUrl()); - setSkeletonURL(settings->value("skeletonModelURL").toUrl()); + setSkeletonModelURL(settings->value("skeletonModelURL").toUrl()); settings->endGroup(); } From 6f638fa62cf19116767e6b0e9bfd56b7f5f7d6a5 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Feb 2014 10:34:34 -0800 Subject: [PATCH 13/42] have domain-server create a UUID for unidentified nodes, closes #1840 --- domain-server/src/DomainServer.cpp | 28 +++++++++++++++++++--------- interface/src/Application.cpp | 1 + interface/src/Application.h | 3 +-- interface/src/avatar/Profile.cpp | 14 -------------- interface/src/avatar/Profile.h | 2 +- libraries/shared/src/NodeList.cpp | 20 ++++++++++++++++++-- libraries/shared/src/NodeList.h | 3 ++- 7 files changed, 42 insertions(+), 29 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 37626e8a43..8c4c9348c0 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -209,6 +209,10 @@ void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSetgetInstance()->nodeWithUUID(nodeUUID)) - { + || nodeList->getInstance()->nodeWithUUID(nodeUUID)) { + + if (nodeUUID.isNull()) { + // this is a check in from an unidentified node + // we need to generate a session UUID for this node + qDebug() << "received a check-in from an unidentified node"; + nodeUUID = QUuid::createUuid(); + qDebug() << "UUID set to" << nodeUUID; + } + SharedNodePointer checkInNode = nodeList->addOrUpdateNode(nodeUUID, nodeType, nodePublicAddress, @@ -291,10 +299,12 @@ void DomainServer::readAvailableDatagrams() { NodeType_t* nodeTypesOfInterest = reinterpret_cast(receivedPacket.data() + packetStream.device()->pos()); + // always send the node their own UUID back + QDataStream broadcastDataStream(&broadcastPacket, QIODevice::Append); + broadcastDataStream << checkInNode->getUUID(); + if (numInterestTypes > 0) { - QDataStream broadcastDataStream(&broadcastPacket, QIODevice::Append); - - // if the node has sent no types of interest, assume they want nothing but their own ID back + // if the node has any interest types, send back those nodes as well foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { if (node->getUUID() != nodeUUID && memchr(nodeTypesOfInterest, node->getType(), numInterestTypes)) { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 868a6fedb1..43a4b61f02 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -205,6 +205,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer))); connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), &_voxels, SLOT(nodeAdded(SharedNodePointer))); connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), &_voxels, SLOT(nodeKilled(SharedNodePointer))); + connect(nodeList, &NodeList::uuidChanged, this, &Application::updateWindowTitle); // read the ApplicationInfo.ini file for Name/Version/Domain information QSettings applicationInfo("resources/info/ApplicationInfo.ini", QSettings::IniFormat); diff --git a/interface/src/Application.h b/interface/src/Application.h index ac93c3f3da..d66bb8143e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -126,8 +126,6 @@ public: void touchEndEvent(QTouchEvent* event); void touchUpdateEvent(QTouchEvent* event); - void updateWindowTitle(); - void wheelEvent(QWheelEvent* event); void makeVoxel(glm::vec3 position, @@ -213,6 +211,7 @@ signals: public slots: void domainChanged(const QString& domainHostname); + void updateWindowTitle(); void nodeAdded(SharedNodePointer node); void nodeKilled(SharedNodePointer node); void packetSent(quint64 length); diff --git a/interface/src/avatar/Profile.cpp b/interface/src/avatar/Profile.cpp index 7f9ae123dc..a2a412199e 100644 --- a/interface/src/avatar/Profile.cpp +++ b/interface/src/avatar/Profile.cpp @@ -41,20 +41,6 @@ QString Profile::getUserString() const { } } -void Profile::setUUID(const QUuid& uuid) { - _uuid = uuid; - - if (!_uuid.isNull()) { - qDebug() << "Changing NodeList owner UUID to" << uuid; - - // when the UUID is changed we need set it appropriately on the NodeList instance - NodeList::getInstance()->setOwnerUUID(uuid); - - // ask for a window title update so the new UUID is presented - Application::getInstance()->updateWindowTitle(); - } -} - void Profile::updateDomain(const QString& domain) { if (_lastDomain != domain) { _lastDomain = domain; diff --git a/interface/src/avatar/Profile.h b/interface/src/avatar/Profile.h index 8a0c021ed6..c32d89cfea 100644 --- a/interface/src/avatar/Profile.h +++ b/interface/src/avatar/Profile.h @@ -28,7 +28,7 @@ public: const QString& getUsername() const { return _username; } - void setUUID(const QUuid& uuid); + void setUUID(const QUuid& uuid) { _uuid = uuid; } const QUuid& getUUID() { return _uuid; } void updateDomain(const QString& domain); diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index d6b8005263..c83a908a7f 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -64,7 +64,7 @@ NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) : _nodeSocket(this), _ownerType(newOwnerType), _nodeTypesOfInterest(), - _ownerUUID(QUuid::createUuid()), + _ownerUUID(), _numNoReplyDomainCheckIns(0), _assignmentServerSocket(), _publicSockAddr(), @@ -492,6 +492,16 @@ void NodeList::sendDomainServerCheckIn() { } } +void NodeList::setOwnerUUID(const QUuid& ownerUUID) { + QUuid oldUUID = _ownerUUID; + _ownerUUID = ownerUUID; + + if (ownerUUID != oldUUID) { + qDebug() << "NodeList UUID changed from" << oldUUID << "to" << _ownerUUID; + emit uuidChanged(ownerUUID); + } +} + int NodeList::processDomainServerList(const QByteArray& packet) { // this is a packet from the domain server, reset the count of un-replied check-ins _numNoReplyDomainCheckIns = 0; @@ -508,7 +518,13 @@ int NodeList::processDomainServerList(const QByteArray& packet) { QDataStream packetStream(packet); packetStream.skipRawData(numBytesForPacketHeader(packet)); - + + // pull our owner UUID from the packet, it's always the first thing + QUuid newUUID; + packetStream >> newUUID; + setOwnerUUID(newUUID); + + // pull each node in the packet while(packetStream.device()->pos() < packet.size()) { packetStream >> nodeType >> nodeUUID >> nodePublicSocket >> nodeLocalSocket; diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 6b8acd6e99..90215a27b5 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -73,7 +73,7 @@ public: unsigned short getDomainPort() const { return _domainSockAddr.getPort(); } const QUuid& getOwnerUUID() const { return _ownerUUID; } - void setOwnerUUID(const QUuid& ownerUUID) { _ownerUUID = ownerUUID; } + void setOwnerUUID(const QUuid& ownerUUID); QUdpSocket& getNodeSocket() { return _nodeSocket; } @@ -124,6 +124,7 @@ public slots: void killNodeWithUUID(const QUuid& nodeUUID); signals: void domainChanged(const QString& domainHostname); + void uuidChanged(const QUuid& ownerUUID); void nodeAdded(SharedNodePointer); void nodeKilled(SharedNodePointer); private: From 3dca04aacb5d1f915525bcf30938c566f7d23f08 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Feb 2014 11:30:53 -0800 Subject: [PATCH 14/42] have the domain-server generate connection secrets, closes #1837 --- domain-server/src/DomainServer.cpp | 41 +++++++++++++++++++----- domain-server/src/DomainServer.h | 4 ++- domain-server/src/DomainServerNodeData.h | 26 +++++++++++++++ libraries/shared/src/Node.cpp | 1 + libraries/shared/src/Node.h | 5 ++- libraries/shared/src/NodeList.cpp | 7 ++-- 6 files changed, 72 insertions(+), 12 deletions(-) create mode 100644 domain-server/src/DomainServerNodeData.h diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 8c4c9348c0..921763d261 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -21,6 +21,8 @@ #include #include +#include "DomainServerNodeData.h" + #include "DomainServer.h" const int RESTART_HOLD_TIME_MSECS = 5 * 1000; @@ -57,8 +59,9 @@ DomainServer::DomainServer(int argc, char* argv[]) : populateDefaultStaticAssignmentsExcludingTypes(parsedTypes); NodeList* nodeList = NodeList::createInstance(NodeType::DomainServer, domainServerPort); - - connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), this, SLOT(nodeKilled(SharedNodePointer))); + + connect(nodeList, &NodeList::nodeAdded, this, &DomainServer::nodeAdded); + connect(nodeList, &NodeList::nodeKilled, this, &DomainServer::nodeKilled); QTimer* silentNodeTimer = new QTimer(this); connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes())); @@ -270,9 +273,7 @@ void DomainServer::readAvailableDatagrams() { if (nodeUUID.isNull()) { // this is a check in from an unidentified node // we need to generate a session UUID for this node - qDebug() << "received a check-in from an unidentified node"; nodeUUID = QUuid::createUuid(); - qDebug() << "UUID set to" << nodeUUID; } SharedNodePointer checkInNode = nodeList->addOrUpdateNode(nodeUUID, @@ -303,14 +304,33 @@ void DomainServer::readAvailableDatagrams() { QDataStream broadcastDataStream(&broadcastPacket, QIODevice::Append); broadcastDataStream << checkInNode->getUUID(); + DomainServerNodeData* nodeData = reinterpret_cast(checkInNode->getLinkedData()); + if (numInterestTypes > 0) { // if the node has any interest types, send back those nodes as well - foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { - if (node->getUUID() != nodeUUID && - memchr(nodeTypesOfInterest, node->getType(), numInterestTypes)) { + foreach (const SharedNodePointer& otherNode, nodeList->getNodeHash()) { + if (otherNode->getUUID() != nodeUUID && + memchr(nodeTypesOfInterest, otherNode->getType(), numInterestTypes)) { // don't send avatar nodes to other avatars, that will come from avatar mixer - broadcastDataStream << *node.data(); + broadcastDataStream << *otherNode.data(); + + // pack the secret that these two nodes will use to communicate with each other + QUuid secretUUID = nodeData->getSessionSecretHash().value(otherNode->getUUID()); + if (secretUUID.isNull()) { + // generate a new secret UUID these two nodes can use + secretUUID = QUuid::createUuid(); + + // set that on the current Node's sessionSecretHash + nodeData->getSessionSecretHash().insert(otherNode->getUUID(), secretUUID); + + // set it on the other Node's sessionSecretHash + reinterpret_cast(otherNode->getLinkedData()) + ->getSessionSecretHash().insert(nodeUUID, secretUUID); + + } + + broadcastDataStream << secretUUID; } } } @@ -556,6 +576,11 @@ void DomainServer::refreshStaticAssignmentAndAddToQueue(SharedAssignmentPointer& _staticAssignmentHash.remove(oldUUID); } +void DomainServer::nodeAdded(SharedNodePointer node) { + // we don't use updateNodeWithData, so add the DomainServerNodeData to the node here + node->setLinkedData(new DomainServerNodeData()); +} + void DomainServer::nodeKilled(SharedNodePointer node) { // if this node's UUID matches a static assignment we need to throw it back in the assignment queue SharedAssignmentPointer matchedAssignment = _staticAssignmentHash.value(node->getUUID()); diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 60251b3bb4..580a758df8 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -30,7 +30,9 @@ public: void exit(int retCode = 0); public slots: - /// Called by NodeList to inform us that a node has been killed. + /// Called by NodeList to inform us a node has been added + void nodeAdded(SharedNodePointer node); + /// Called by NodeList to inform us a node has been killed void nodeKilled(SharedNodePointer node); private: diff --git a/domain-server/src/DomainServerNodeData.h b/domain-server/src/DomainServerNodeData.h new file mode 100644 index 0000000000..ea56e31f1c --- /dev/null +++ b/domain-server/src/DomainServerNodeData.h @@ -0,0 +1,26 @@ +// +// DomainServerNodeData.h +// hifi +// +// Created by Stephen Birarda on 2/6/2014. +// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. +// + +#ifndef __hifi__DomainServerNodeData__ +#define __hifi__DomainServerNodeData__ + +#include + +#include + +class DomainServerNodeData : public NodeData { +public: + DomainServerNodeData() : _sessionSecretHash() {}; + int parseData(const QByteArray& packet) { return 0; } + + QHash& getSessionSecretHash() { return _sessionSecretHash; } +private: + QHash _sessionSecretHash; +}; + +#endif /* defined(__hifi__DomainServerNodeData__) */ diff --git a/libraries/shared/src/Node.cpp b/libraries/shared/src/Node.cpp index 8efbf5782a..bb45265f8b 100644 --- a/libraries/shared/src/Node.cpp +++ b/libraries/shared/src/Node.cpp @@ -52,6 +52,7 @@ Node::Node(const QUuid& uuid, char type, const HifiSockAddr& publicSocket, const _publicSocket(publicSocket), _localSocket(localSocket), _activeSocket(NULL), + _connectionSecret(), _bytesReceivedMovingAverage(NULL), _linkedData(NULL), _isAlive(true), diff --git a/libraries/shared/src/Node.h b/libraries/shared/src/Node.h index 952e1b1be2..43ec5baf81 100644 --- a/libraries/shared/src/Node.h +++ b/libraries/shared/src/Node.h @@ -56,7 +56,6 @@ public: char getType() const { return _type; } void setType(char type) { _type = type; } - const QUuid& getUUID() const { return _uuid; } void setUUID(const QUuid& uuid) { _uuid = uuid; } @@ -76,6 +75,9 @@ public: void activatePublicSocket(); void activateLocalSocket(); + + const QUuid& getConnectionSecret() const { return _connectionSecret; } + void setConnectionSecret(const QUuid& connectionSecret) { _connectionSecret = connectionSecret; } NodeData* getLinkedData() const { return _linkedData; } void setLinkedData(NodeData* linkedData) { _linkedData = linkedData; } @@ -109,6 +111,7 @@ private: HifiSockAddr _publicSocket; HifiSockAddr _localSocket; HifiSockAddr* _activeSocket; + QUuid _connectionSecret; SimpleMovingAverage* _bytesReceivedMovingAverage; NodeData* _linkedData; bool _isAlive; diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index c83a908a7f..4b5fdfeaa6 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -511,7 +511,7 @@ int NodeList::processDomainServerList(const QByteArray& packet) { // setup variables to read into from QDataStream qint8 nodeType; - QUuid nodeUUID; + QUuid nodeUUID, connectionUUID; HifiSockAddr nodePublicSocket; HifiSockAddr nodeLocalSocket; @@ -534,7 +534,10 @@ int NodeList::processDomainServerList(const QByteArray& packet) { nodePublicSocket.setAddress(_domainSockAddr.getAddress()); } - addOrUpdateNode(nodeUUID, nodeType, nodePublicSocket, nodeLocalSocket); + SharedNodePointer node = addOrUpdateNode(nodeUUID, nodeType, nodePublicSocket, nodeLocalSocket); + + packetStream >> connectionUUID; + node->setConnectionSecret(connectionUUID); } return readNodes; From f02e1aaf4790896d11b26ed218efb63eca67908f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Feb 2014 11:37:52 -0800 Subject: [PATCH 15/42] cleanup the alive half of connection secrets when node dies --- domain-server/src/DomainServer.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 921763d261..e847143eaf 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -588,6 +588,15 @@ void DomainServer::nodeKilled(SharedNodePointer node) { if (matchedAssignment) { refreshStaticAssignmentAndAddToQueue(matchedAssignment); } + + // cleanup the connection secrets that we set up for this node (on the other nodes) + DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); + foreach (const QUuid& otherNodeSessionUUID, nodeData->getSessionSecretHash().keys()) { + SharedNodePointer otherNode = NodeList::getInstance()->nodeWithUUID(otherNodeSessionUUID); + if (otherNode) { + reinterpret_cast(otherNode->getLinkedData())->getSessionSecretHash().remove(node->getUUID()); + } + } } SharedAssignmentPointer DomainServer::matchingStaticAssignmentForCheckIn(const QUuid& checkInUUID, NodeType_t nodeType) { From e72f6d16cc6cbdf3b8ae7d53437da2a0d20092cf Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Feb 2014 11:43:23 -0800 Subject: [PATCH 16/42] rename NodeList ownerUUID to sessionUUID --- assignment-client/src/AssignmentClient.cpp | 2 +- interface/src/Application.cpp | 2 +- libraries/avatars/src/AvatarData.h | 2 +- .../src/DataServerScriptingInterface.cpp | 2 +- libraries/shared/src/NodeList.cpp | 18 +++++++++--------- libraries/shared/src/NodeList.h | 6 +++--- libraries/shared/src/PacketHeaders.cpp | 2 +- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index b2a5555e36..b294f48fac 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -131,7 +131,7 @@ void AssignmentClient::readPendingDatagrams() { // switch our nodelist domain IP and port to whoever sent us the assignment nodeList->setDomainSockAddr(senderSockAddr); - nodeList->setOwnerUUID(_currentAssignment->getUUID()); + nodeList->setSessionUUID(_currentAssignment->getUUID()); qDebug() << "Destination IP for assignment is" << nodeList->getDomainIP().toString(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 43a4b61f02..c492fc8fc9 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3850,7 +3850,7 @@ void Application::updateWindowTitle(){ QString buildVersion = " (build " + applicationVersion() + ")"; NodeList* nodeList = NodeList::getInstance(); - QString title = QString() + _profile.getUsername() + " " + nodeList->getOwnerUUID().toString() + QString title = QString() + _profile.getUsername() + " " + nodeList->getSessionUUID().toString() + " @ " + nodeList->getDomainHostname() + buildVersion; qDebug("Application title set to: %s", title.toStdString().c_str()); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 5e4f7acb2c..56d345ce75 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -73,7 +73,7 @@ class AvatarData : public NodeData { Q_PROPERTY(glm::quat orientation READ getOrientation WRITE setOrientation) Q_PROPERTY(float headPitch READ getHeadPitch WRITE setHeadPitch) - + public: AvatarData(); ~AvatarData(); diff --git a/libraries/script-engine/src/DataServerScriptingInterface.cpp b/libraries/script-engine/src/DataServerScriptingInterface.cpp index 6effd7ebdc..04efed2bce 100644 --- a/libraries/script-engine/src/DataServerScriptingInterface.cpp +++ b/libraries/script-engine/src/DataServerScriptingInterface.cpp @@ -17,5 +17,5 @@ DataServerScriptingInterface::DataServerScriptingInterface() } void DataServerScriptingInterface::setValueForKey(const QString& key, const QString& value) { - DataServerClient::putValueForKeyAndUUID(key, value, NodeList::getInstance()->getOwnerUUID()); + DataServerClient::putValueForKeyAndUUID(key, value, NodeList::getInstance()->getSessionUUID()); } \ No newline at end of file diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 4b5fdfeaa6..e357dd130e 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -64,7 +64,7 @@ NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) : _nodeSocket(this), _ownerType(newOwnerType), _nodeTypesOfInterest(), - _ownerUUID(), + _sessionUUID(), _numNoReplyDomainCheckIns(0), _assignmentServerSocket(), _publicSockAddr(), @@ -257,7 +257,7 @@ void NodeList::reset() { _nodeTypesOfInterest.clear(); // refresh the owner UUID - _ownerUUID = QUuid::createUuid(); + _sessionUUID = QUuid::createUuid(); } void NodeList::addNodeTypeToInterestSet(NodeType_t nodeTypeToAdd) { @@ -492,13 +492,13 @@ void NodeList::sendDomainServerCheckIn() { } } -void NodeList::setOwnerUUID(const QUuid& ownerUUID) { - QUuid oldUUID = _ownerUUID; - _ownerUUID = ownerUUID; +void NodeList::setSessionUUID(const QUuid& sessionUUID) { + QUuid oldUUID = _sessionUUID; + _sessionUUID = sessionUUID; - if (ownerUUID != oldUUID) { - qDebug() << "NodeList UUID changed from" << oldUUID << "to" << _ownerUUID; - emit uuidChanged(ownerUUID); + if (sessionUUID != oldUUID) { + qDebug() << "NodeList UUID changed from" << oldUUID << "to" << _sessionUUID; + emit uuidChanged(sessionUUID); } } @@ -522,7 +522,7 @@ int NodeList::processDomainServerList(const QByteArray& packet) { // pull our owner UUID from the packet, it's always the first thing QUuid newUUID; packetStream >> newUUID; - setOwnerUUID(newUUID); + setSessionUUID(newUUID); // pull each node in the packet while(packetStream.device()->pos() < packet.size()) { diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 90215a27b5..daac87da28 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -72,8 +72,8 @@ public: unsigned short getDomainPort() const { return _domainSockAddr.getPort(); } - const QUuid& getOwnerUUID() const { return _ownerUUID; } - void setOwnerUUID(const QUuid& ownerUUID); + const QUuid& getSessionUUID() const { return _sessionUUID; } + void setSessionUUID(const QUuid& sessionUUID); QUdpSocket& getNodeSocket() { return _nodeSocket; } @@ -146,7 +146,7 @@ private: QUdpSocket _nodeSocket; NodeType_t _ownerType; NodeSet _nodeTypesOfInterest; - QUuid _ownerUUID; + QUuid _sessionUUID; int _numNoReplyDomainCheckIns; HifiSockAddr _assignmentServerSocket; HifiSockAddr _publicSockAddr; diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index 16e7cca1c1..d350a8335c 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -69,7 +69,7 @@ int populatePacketHeader(char* packet, PacketType type, const QUuid& connectionU int numTypeBytes = packArithmeticallyCodedValue(type, packet); packet[numTypeBytes] = versionForPacketType(type); - QUuid packUUID = connectionUUID.isNull() ? NodeList::getInstance()->getOwnerUUID() : connectionUUID; + QUuid packUUID = connectionUUID.isNull() ? NodeList::getInstance()->getSessionUUID() : connectionUUID; QByteArray rfcUUID = packUUID.toRfc4122(); memcpy(packet + numTypeBytes + sizeof(PacketVersion), rfcUUID.constData(), NUM_BYTES_RFC4122_UUID); From f10404b31e8d3edb1e867f5bf87ed2bc639976bb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Feb 2014 11:45:37 -0800 Subject: [PATCH 17/42] allow setting of avatar URLs via AvatarData properties --- libraries/avatars/src/AvatarData.h | 2 ++ .../src/DataServerScriptingInterface.cpp | 21 ---------------- .../src/DataServerScriptingInterface.h | 25 ------------------- libraries/script-engine/src/ScriptEngine.cpp | 2 -- libraries/script-engine/src/ScriptEngine.h | 5 ---- 5 files changed, 2 insertions(+), 53 deletions(-) delete mode 100644 libraries/script-engine/src/DataServerScriptingInterface.cpp delete mode 100644 libraries/script-engine/src/DataServerScriptingInterface.h diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 56d345ce75..a08441fb93 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -74,6 +74,8 @@ class AvatarData : public NodeData { Q_PROPERTY(glm::quat orientation READ getOrientation WRITE setOrientation) Q_PROPERTY(float headPitch READ getHeadPitch WRITE setHeadPitch) + Q_PROPERTY(QUrl faceModelURL READ getFaceModelURL WRITE setFaceModelURL) + Q_PROPERTY(QURl skeletonModelURL READ getSkeletonModelURL WRITE setSkeletonModelURL) public: AvatarData(); ~AvatarData(); diff --git a/libraries/script-engine/src/DataServerScriptingInterface.cpp b/libraries/script-engine/src/DataServerScriptingInterface.cpp deleted file mode 100644 index 04efed2bce..0000000000 --- a/libraries/script-engine/src/DataServerScriptingInterface.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// -// DataServerScriptingInterface.cpp -// hifi -// -// Created by Stephen Birarda on 1/20/2014. -// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. -// - -#include -#include - -#include "DataServerScriptingInterface.h" - -DataServerScriptingInterface::DataServerScriptingInterface() -{ - -} - -void DataServerScriptingInterface::setValueForKey(const QString& key, const QString& value) { - DataServerClient::putValueForKeyAndUUID(key, value, NodeList::getInstance()->getSessionUUID()); -} \ No newline at end of file diff --git a/libraries/script-engine/src/DataServerScriptingInterface.h b/libraries/script-engine/src/DataServerScriptingInterface.h deleted file mode 100644 index b46c0bda7a..0000000000 --- a/libraries/script-engine/src/DataServerScriptingInterface.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// DataServerScriptingInterface.h -// hifi -// -// Created by Stephen Birarda on 1/20/2014. -// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. -// - -#ifndef __hifi__DataServerScriptingInterface__ -#define __hifi__DataServerScriptingInterface__ - -#include -#include -#include - -class DataServerScriptingInterface : public QObject { - Q_OBJECT -public: - DataServerScriptingInterface(); - -public slots: - void setValueForKey(const QString& key, const QString& value); -}; - -#endif /* defined(__hifi__DataServerScriptingInterface__) */ diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index b3b0736114..e428975024 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -44,7 +44,6 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems, co AbstractMenuInterface* menu, AbstractControllerScriptingInterface* controllerScriptingInterface) : _isAvatar(false), - _dataServerScriptingInterface(), _avatarData(NULL) { _scriptContents = scriptContents; @@ -137,7 +136,6 @@ void ScriptEngine::init() { registerGlobalObject("Script", this); registerGlobalObject("Audio", &_audioScriptingInterface); registerGlobalObject("Controller", _controllerScriptingInterface); - registerGlobalObject("Data", &_dataServerScriptingInterface); registerGlobalObject("Particles", &_particlesScriptingInterface); registerGlobalObject("Quat", &_quatLibrary); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 98d5860332..5a6864b12f 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -24,7 +24,6 @@ class ParticlesScriptingInterface; #include "AbstractControllerScriptingInterface.h" -#include "DataServerScriptingInterface.h" #include "Quat.h" const QString NO_SCRIPT(""); @@ -43,9 +42,6 @@ public: /// Access the ParticlesScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener static ParticlesScriptingInterface* getParticlesScriptingInterface() { return &_particlesScriptingInterface; } - - /// Access the DataServerScriptingInterface for access to its underlying UUID - const DataServerScriptingInterface& getDataServerScriptingInterface() { return _dataServerScriptingInterface; } /// sets the script contents, will return false if failed, will fail if script is already running bool setScriptContents(const QString& scriptContents); @@ -97,7 +93,6 @@ private: static ParticlesScriptingInterface _particlesScriptingInterface; AbstractControllerScriptingInterface* _controllerScriptingInterface; AudioScriptingInterface _audioScriptingInterface; - DataServerScriptingInterface _dataServerScriptingInterface; AvatarData* _avatarData; bool _wantMenuItems; QString _scriptMenuName; From cb6316bf4d51c3aa6899650599c728013aa66e3e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Feb 2014 11:45:52 -0800 Subject: [PATCH 18/42] fix KeyState enum spacing --- libraries/avatars/src/AvatarData.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index a08441fb93..21e2042487 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -52,8 +52,7 @@ static const float MIN_AVATAR_SCALE = .005f; const float MAX_AUDIO_LOUDNESS = 1000.0; // close enough for mouth animation -enum KeyState -{ +enum KeyState { NO_KEY_DOWN = 0, INSERT_KEY_DOWN, DELETE_KEY_DOWN From a823722d27e65cfc6c102e6a0ce2edb61802fb63 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Feb 2014 14:28:58 -0800 Subject: [PATCH 19/42] add writeDatagram helper to NodeList to insert md5 hash --- animation-server/src/AnimationServer.cpp | 8 ++++- assignment-client/src/Agent.cpp | 27 ++++++++++------ assignment-client/src/audio/AudioMixer.cpp | 4 +-- assignment-client/src/avatars/AvatarMixer.cpp | 8 ++--- .../src/octree/OctreeSendThread.cpp | 18 ++++------- assignment-client/src/octree/OctreeServer.cpp | 22 +++++++------ .../src/particles/ParticleServer.cpp | 8 ++--- assignment-client/src/voxels/VoxelServer.cpp | 4 +-- interface/src/Application.cpp | 5 +-- interface/src/Audio.cpp | 7 ++--- interface/src/DatagramProcessor.cpp | 12 +++++-- interface/src/MetavoxelSystem.cpp | 5 +-- libraries/audio/src/AudioInjector.cpp | 4 +-- libraries/avatars/src/AvatarData.h | 2 +- libraries/octree/src/JurisdictionListener.cpp | 3 +- libraries/octree/src/JurisdictionSender.cpp | 3 +- .../octree/src/OctreeEditPacketSender.cpp | 3 +- libraries/shared/src/NetworkPacket.cpp | 16 +++++----- libraries/shared/src/NetworkPacket.h | 8 ++--- libraries/shared/src/NodeList.cpp | 31 +++++++++++++++++++ libraries/shared/src/NodeList.h | 5 +++ libraries/shared/src/PacketHeaders.cpp | 17 +++++++--- libraries/shared/src/PacketHeaders.h | 5 ++- libraries/shared/src/PacketSender.cpp | 8 ++--- libraries/shared/src/PacketSender.h | 2 +- .../shared/src/ReceivedPacketProcessor.cpp | 12 +++---- .../shared/src/ReceivedPacketProcessor.h | 2 +- 27 files changed, 142 insertions(+), 107 deletions(-) diff --git a/animation-server/src/AnimationServer.cpp b/animation-server/src/AnimationServer.cpp index 24ea7ede9c..466ed7cf93 100644 --- a/animation-server/src/AnimationServer.cpp +++ b/animation-server/src/AnimationServer.cpp @@ -835,7 +835,13 @@ void AnimationServer::readPendingDatagrams() { int headerBytes = numBytesForPacketHeader(receivedPacket); // PacketType_JURISDICTION, first byte is the node type... if (receivedPacket.data()[headerBytes] == NodeType::VoxelServer && ::jurisdictionListener) { - ::jurisdictionListener->queueReceivedPacket(nodeSockAddr, receivedPacket); + QUuid nodeUUID; + deconstructPacketHeader(receivedPacket, nodeUUID); + + SharedNodePointer matchedNode = NodeList::getInstance()->nodeWithUUID(nodeUUID); + if (matchedNode) { + ::jurisdictionListener->queueReceivedPacket(matchedNode, receivedPacket); + } } } NodeList::getInstance()->processNodeData(nodeSockAddr, receivedPacket); diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 93ec4bf991..eff573216a 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -35,17 +35,24 @@ void Agent::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& PacketType datagramPacketType = packetTypeForPacket(dataByteArray); if (datagramPacketType == PacketTypeJurisdiction) { int headerBytes = numBytesForPacketHeader(dataByteArray); - // PacketType_JURISDICTION, first byte is the node type... - switch (dataByteArray[headerBytes]) { - case NodeType::VoxelServer: - _scriptEngine.getVoxelsScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(senderSockAddr, - dataByteArray); - break; - case NodeType::ParticleServer: - _scriptEngine.getParticlesScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(senderSockAddr, - dataByteArray); - break; + + QUuid nodeUUID; + SharedNodePointer matchedNode = NodeList::getInstance()->nodeWithUUID(nodeUUID); + + if (matchedNode) { + // PacketType_JURISDICTION, first byte is the node type... + switch (dataByteArray[headerBytes]) { + case NodeType::VoxelServer: + _scriptEngine.getVoxelsScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(matchedNode, + dataByteArray); + break; + case NodeType::ParticleServer: + _scriptEngine.getParticlesScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(matchedNode, + dataByteArray); + break; + } } + } else if (datagramPacketType == PacketTypeParticleAddResponse) { // this will keep creatorTokenIDs to IDs mapped correctly Particle::handleAddParticleResponse(dataByteArray); diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 90e2810f27..e9c0aafabb 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -279,9 +279,7 @@ void AudioMixer::run() { prepareMixForListeningNode(node.data()); memcpy(clientPacket + numBytesPacketHeader, _clientSamples, sizeof(_clientSamples)); - nodeList->getNodeSocket().writeDatagram((char*) clientPacket, sizeof(clientPacket), - node->getActiveSocket()->getAddress(), - node->getActiveSocket()->getPort()); + nodeList->writeDatagram((char*) clientPacket, sizeof(clientPacket), node); } } diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index ecf9bfe4b2..5b085fbcd2 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -73,9 +73,7 @@ void broadcastAvatarData() { avatarByteArray.append(nodeData->toByteArray()); if (avatarByteArray.size() + mixedAvatarByteArray.size() > MAX_PACKET_SIZE) { - nodeList->getNodeSocket().writeDatagram(mixedAvatarByteArray, - node->getActiveSocket()->getAddress(), - node->getActiveSocket()->getPort()); + nodeList->writeDatagram(mixedAvatarByteArray, node); // reset the packet mixedAvatarByteArray.resize(numPacketHeaderBytes); @@ -86,9 +84,7 @@ void broadcastAvatarData() { } } - nodeList->getNodeSocket().writeDatagram(mixedAvatarByteArray, - node->getActiveSocket()->getAddress(), - node->getActiveSocket()->getPort()); + nodeList->writeDatagram(mixedAvatarByteArray, node); } } } diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index a016553e5f..5672cd7cac 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -142,15 +142,11 @@ int OctreeSendThread::handlePacketSend(Node* node, OctreeQueryNode* nodeData, in } // actually send it - NodeList::getInstance()->getNodeSocket().writeDatagram((char*) statsMessage, statsMessageLength, - nodeAddress->getAddress(), - nodeAddress->getPort()); + NodeList::getInstance()->writeDatagram((char*) statsMessage, statsMessageLength, SharedNodePointer(node)); packetSent = true; } else { // not enough room in the packet, send two packets - NodeList::getInstance()->getNodeSocket().writeDatagram((char*) statsMessage, statsMessageLength, - nodeAddress->getAddress(), - nodeAddress->getPort()); + NodeList::getInstance()->writeDatagram((char*) statsMessage, statsMessageLength, SharedNodePointer(node)); // since a stats message is only included on end of scene, don't consider any of these bytes "wasted", since // there was nothing else to send. @@ -168,9 +164,8 @@ int OctreeSendThread::handlePacketSend(Node* node, OctreeQueryNode* nodeData, in truePacketsSent++; packetsSent++; - NodeList::getInstance()->getNodeSocket().writeDatagram((char*) nodeData->getPacket(), nodeData->getPacketLength(), - nodeAddress->getAddress(), - nodeAddress->getPort()); + NodeList::getInstance()->writeDatagram((char*) nodeData->getPacket(), nodeData->getPacketLength(), + SharedNodePointer(node)); packetSent = true; @@ -189,9 +184,8 @@ int OctreeSendThread::handlePacketSend(Node* node, OctreeQueryNode* nodeData, in // If there's actually a packet waiting, then send it. if (nodeData->isPacketWaiting()) { // just send the voxel packet - NodeList::getInstance()->getNodeSocket().writeDatagram((char*) nodeData->getPacket(), nodeData->getPacketLength(), - nodeAddress->getAddress(), - nodeAddress->getPort()); + NodeList::getInstance()->writeDatagram((char*) nodeData->getPacket(), nodeData->getPacketLength(), + SharedNodePointer(node)); packetSent = true; int thisWastedBytes = MAX_PACKET_SIZE - nodeData->getPacketLength(); diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 6e58a0a987..10dc22fa96 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -462,6 +462,11 @@ void OctreeServer::processDatagram(const QByteArray& dataByteArray, const HifiSo NodeList* nodeList = NodeList::getInstance(); PacketType packetType = packetTypeForPacket(dataByteArray); + + QUuid nodeUUID; + deconstructPacketHeader(dataByteArray, nodeUUID); + + SharedNodePointer matchingNode = nodeList->nodeWithUUID(nodeUUID); if (packetType == getMyQueryMessageType()) { bool debug = false; @@ -471,27 +476,24 @@ void OctreeServer::processDatagram(const QByteArray& dataByteArray, const HifiSo // If we got a PacketType_VOXEL_QUERY, then we're talking to an NodeType_t_AVATAR, and we // need to make sure we have it in our nodeList. - QUuid nodeUUID; - deconstructPacketHeader(dataByteArray, nodeUUID); - SharedNodePointer node = nodeList->nodeWithUUID(nodeUUID); - if (node) { - nodeList->updateNodeWithData(node.data(), senderSockAddr, dataByteArray); - if (!node->getActiveSocket()) { + if (matchingNode) { + nodeList->updateNodeWithData(matchingNode.data(), senderSockAddr, dataByteArray); + if (!matchingNode->getActiveSocket()) { // we don't have an active socket for this node, but they're talking to us // this means they've heard from us and can reply, let's assume public is active - node->activatePublicSocket(); + matchingNode->activatePublicSocket(); } - OctreeQueryNode* nodeData = (OctreeQueryNode*) node->getLinkedData(); + OctreeQueryNode* nodeData = (OctreeQueryNode*) matchingNode->getLinkedData(); if (nodeData && !nodeData->isOctreeSendThreadInitalized()) { nodeData->initializeOctreeSendThread(this, nodeUUID); } } } else if (packetType == PacketTypeJurisdictionRequest) { - _jurisdictionSender->queueReceivedPacket(senderSockAddr, dataByteArray); + _jurisdictionSender->queueReceivedPacket(matchingNode, dataByteArray); } else if (_octreeInboundPacketProcessor && getOctree()->handlesEditPacketType(packetType)) { - _octreeInboundPacketProcessor->queueReceivedPacket(senderSockAddr, dataByteArray); + _octreeInboundPacketProcessor->queueReceivedPacket(matchingNode, dataByteArray); } else { // let processNodeData handle it. NodeList::getInstance()->processNodeData(senderSockAddr, dataByteArray); diff --git a/assignment-client/src/particles/ParticleServer.cpp b/assignment-client/src/particles/ParticleServer.cpp index 9344d8c4ae..db546f5960 100644 --- a/assignment-client/src/particles/ParticleServer.cpp +++ b/assignment-client/src/particles/ParticleServer.cpp @@ -63,9 +63,7 @@ void ParticleServer::particleCreated(const Particle& newParticle, Node* node) { copyAt += sizeof(particleID); packetLength += sizeof(particleID); - NodeList::getInstance()->getNodeSocket().writeDatagram((char*) outputBuffer, packetLength, - node->getActiveSocket()->getAddress(), - node->getActiveSocket()->getPort()); + NodeList::getInstance()->writeDatagram((char*) outputBuffer, packetLength, SharedNodePointer(node)); } @@ -104,9 +102,7 @@ int ParticleServer::sendSpecialPacket(Node* node) { //qDebug() << "sending PacketType_PARTICLE_ERASE packetLength:" << packetLength; - NodeList::getInstance()->getNodeSocket().writeDatagram((char*) outputBuffer, packetLength, - node->getActiveSocket()->getAddress(), - node->getActiveSocket()->getPort()); + NodeList::getInstance()->writeDatagram((char*) outputBuffer, packetLength, SharedNodePointer(node)); } nodeData->setLastDeletedParticlesSentAt(deletePacketSentAt); diff --git a/assignment-client/src/voxels/VoxelServer.cpp b/assignment-client/src/voxels/VoxelServer.cpp index b71bcd3dc2..1edec370bc 100644 --- a/assignment-client/src/voxels/VoxelServer.cpp +++ b/assignment-client/src/voxels/VoxelServer.cpp @@ -46,9 +46,7 @@ int VoxelServer::sendSpecialPacket(Node* node) { envPacketLength += getEnvironmentData(i)->getBroadcastData(_tempOutputBuffer + envPacketLength); } - NodeList::getInstance()->getNodeSocket().writeDatagram((char*) _tempOutputBuffer, envPacketLength, - node->getActiveSocket()->getAddress(), - node->getActiveSocket()->getPort()); + NodeList::getInstance()->writeDatagram((char*) _tempOutputBuffer, envPacketLength, SharedNodePointer(node)); return envPacketLength; } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c492fc8fc9..bd7f57d595 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2543,10 +2543,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node int packetLength = endOfVoxelQueryPacket - voxelQueryPacket; // make sure we still have an active socket - if (node->getActiveSocket()) { - nodeList->getNodeSocket().writeDatagram((char*) voxelQueryPacket, packetLength, - node->getActiveSocket()->getAddress(), node->getActiveSocket()->getPort()); - } + nodeList->writeDatagram(reinterpret_cast(voxelQueryPacket), packetLength, node); // Feed number of bytes to corresponding channel of the bandwidth meter _bandwidthMeter.outputStream(BandwidthMeter::VOXELS).updateValue(packetLength); diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 3689c4462e..4acda2fe9b 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -409,10 +409,9 @@ void Audio::handleAudioInput() { memcpy(currentPacketPtr, &headOrientation, sizeof(headOrientation)); currentPacketPtr += sizeof(headOrientation); - nodeList->getNodeSocket().writeDatagram(monoAudioDataPacket, - NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes, - audioMixer->getActiveSocket()->getAddress(), - audioMixer->getActiveSocket()->getPort()); + nodeList->writeDatagram(monoAudioDataPacket, + NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes, + audioMixer); Application::getInstance()->getBandwidthMeter()->outputStream(BandwidthMeter::AUDIO) .updateValue(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes); diff --git a/interface/src/DatagramProcessor.cpp b/interface/src/DatagramProcessor.cpp index 64cd2f618e..f0cd2eb168 100644 --- a/interface/src/DatagramProcessor.cpp +++ b/interface/src/DatagramProcessor.cpp @@ -84,8 +84,16 @@ void DatagramProcessor::processDatagrams() { printf("got PacketType_VOXEL_DATA, sequence:%d flightTime:%d\n", sequence, flightTime); } - // add this packet to our list of voxel packets and process them on the voxel processing - application->_voxelProcessor.queueReceivedPacket(senderSockAddr, incomingPacket); + QUuid nodeUUID; + deconstructPacketHeader(incomingPacket, nodeUUID); + + SharedNodePointer matchedNode = NodeList::getInstance()->nodeWithUUID(nodeUUID); + + if (matchedNode) { + // add this packet to our list of voxel packets and process them on the voxel processing + application->_voxelProcessor.queueReceivedPacket(matchedNode, incomingPacket); + } + break; } case PacketTypeMetavoxelData: diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 311c8f2556..60d56b8ba8 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -226,10 +226,7 @@ void MetavoxelClient::receivedData(const QByteArray& data) { void MetavoxelClient::sendData(const QByteArray& data) { QMutexLocker locker(&_node->getMutex()); - const HifiSockAddr* address = _node->getActiveSocket(); - if (address) { - NodeList::getInstance()->getNodeSocket().writeDatagram(data, address->getAddress(), address->getPort()); - } + NodeList::getInstance()->writeDatagram(data, _node); } void MetavoxelClient::readPacket(Bitstream& in) { diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 325cd06639..6dd7342eba 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -95,9 +95,7 @@ void AudioInjector::injectAudio() { if (audioMixer && nodeList->getNodeActiveSocketOrPing(audioMixer.data())) { // send off this audio packet - nodeList->getNodeSocket().writeDatagram(injectAudioPacket, - audioMixer->getActiveSocket()->getAddress(), - audioMixer->getActiveSocket()->getPort()); + nodeList->writeDatagram(injectAudioPacket, audioMixer); } currentSendPosition += bytesToCopy; diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 21e2042487..5c3c9ad9af 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -74,7 +74,7 @@ class AvatarData : public NodeData { Q_PROPERTY(float headPitch READ getHeadPitch WRITE setHeadPitch) Q_PROPERTY(QUrl faceModelURL READ getFaceModelURL WRITE setFaceModelURL) - Q_PROPERTY(QURl skeletonModelURL READ getSkeletonModelURL WRITE setSkeletonModelURL) + Q_PROPERTY(QUrl skeletonModelURL READ getSkeletonModelURL WRITE setSkeletonModelURL) public: AvatarData(); ~AvatarData(); diff --git a/libraries/octree/src/JurisdictionListener.cpp b/libraries/octree/src/JurisdictionListener.cpp index d2c24021ac..4d17536313 100644 --- a/libraries/octree/src/JurisdictionListener.cpp +++ b/libraries/octree/src/JurisdictionListener.cpp @@ -46,8 +46,7 @@ bool JurisdictionListener::queueJurisdictionRequest() { foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { if (nodeList->getNodeActiveSocketOrPing(node.data()) && node->getType() == getNodeType()) { - const HifiSockAddr* nodeAddress = node->getActiveSocket(); - _packetSender.queuePacketForSending(*nodeAddress, QByteArray(reinterpret_cast(bufferOut), sizeOut)); + _packetSender.queuePacketForSending(node, QByteArray(reinterpret_cast(bufferOut), sizeOut)); nodeCount++; } } diff --git a/libraries/octree/src/JurisdictionSender.cpp b/libraries/octree/src/JurisdictionSender.cpp index 854496e40f..c540123a8c 100644 --- a/libraries/octree/src/JurisdictionSender.cpp +++ b/libraries/octree/src/JurisdictionSender.cpp @@ -65,8 +65,7 @@ bool JurisdictionSender::process() { SharedNodePointer node = NodeList::getInstance()->nodeWithUUID(nodeUUID); if (node && node->getActiveSocket() != NULL) { - const HifiSockAddr* nodeAddress = node->getActiveSocket(); - _packetSender.queuePacketForSending(*nodeAddress, QByteArray(reinterpret_cast(bufferOut), sizeOut)); + _packetSender.queuePacketForSending(node, QByteArray(reinterpret_cast(bufferOut), sizeOut)); nodeCount++; } } diff --git a/libraries/octree/src/OctreeEditPacketSender.cpp b/libraries/octree/src/OctreeEditPacketSender.cpp index 5b84b819cc..f7b60b3d3f 100644 --- a/libraries/octree/src/OctreeEditPacketSender.cpp +++ b/libraries/octree/src/OctreeEditPacketSender.cpp @@ -92,8 +92,7 @@ void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned c if (node->getType() == getMyNodeType() && ((node->getUUID() == nodeUUID) || (nodeUUID.isNull()))) { if (nodeList->getNodeActiveSocketOrPing(node.data())) { - const HifiSockAddr* nodeAddress = node->getActiveSocket(); - queuePacketForSending(*nodeAddress, QByteArray(reinterpret_cast(buffer), length)); + queuePacketForSending(node, QByteArray(reinterpret_cast(buffer), length)); // debugging output... bool wantDebugging = false; diff --git a/libraries/shared/src/NetworkPacket.cpp b/libraries/shared/src/NetworkPacket.cpp index aacd95dbbf..e63226bd3a 100644 --- a/libraries/shared/src/NetworkPacket.cpp +++ b/libraries/shared/src/NetworkPacket.cpp @@ -14,9 +14,9 @@ #include "NetworkPacket.h" -void NetworkPacket::copyContents(const HifiSockAddr& sockAddr, const QByteArray& packet) { +void NetworkPacket::copyContents(const SharedNodePointer& destinationNode, const QByteArray& packet) { if (packet.size() && packet.size() <= MAX_PACKET_SIZE) { - _sockAddr = sockAddr; + _destinationNode = destinationNode; _byteArray = packet; } else { qDebug(">>> NetworkPacket::copyContents() unexpected length = %d", packet.size()); @@ -24,28 +24,28 @@ void NetworkPacket::copyContents(const HifiSockAddr& sockAddr, const QByteArray& } NetworkPacket::NetworkPacket(const NetworkPacket& packet) { - copyContents(packet.getSockAddr(), packet.getByteArray()); + copyContents(packet.getDestinationNode(), packet.getByteArray()); } -NetworkPacket::NetworkPacket(const HifiSockAddr& sockAddr, const QByteArray& packet) { - copyContents(sockAddr, packet); +NetworkPacket::NetworkPacket(const SharedNodePointer& destinationNode, const QByteArray& packet) { + copyContents(destinationNode, packet); }; // copy assignment NetworkPacket& NetworkPacket::operator=(NetworkPacket const& other) { - copyContents(other.getSockAddr(), other.getByteArray()); + copyContents(other.getDestinationNode(), other.getByteArray()); return *this; } #ifdef HAS_MOVE_SEMANTICS // move, same as copy, but other packet won't be used further NetworkPacket::NetworkPacket(NetworkPacket && packet) { - copyContents(packet.getAddress(), packet.getByteArray()); + copyContents(packet.getDestinationNode(), packet.getByteArray()); } // move assignment NetworkPacket& NetworkPacket::operator=(NetworkPacket&& other) { - copyContents(other.getAddress(), other.getByteArray()); + copyContents(other.getDestinationNode(), other.getByteArray()); return *this; } #endif \ No newline at end of file diff --git a/libraries/shared/src/NetworkPacket.h b/libraries/shared/src/NetworkPacket.h index 480a793a49..ea3846da0a 100644 --- a/libraries/shared/src/NetworkPacket.h +++ b/libraries/shared/src/NetworkPacket.h @@ -33,15 +33,15 @@ public: NetworkPacket& operator= (NetworkPacket&& other); // move assignment #endif - NetworkPacket(const HifiSockAddr& sockAddr, const QByteArray& byteArray); + NetworkPacket(const SharedNodePointer& destinationNode, const QByteArray& byteArray); - const HifiSockAddr& getSockAddr() const { return _sockAddr; } + const SharedNodePointer& getDestinationNode() const { return _destinationNode; } const QByteArray& getByteArray() const { return _byteArray; } private: - void copyContents(const HifiSockAddr& sockAddr, const QByteArray& byteArray); + void copyContents(const SharedNodePointer& destinationNode, const QByteArray& byteArray); - HifiSockAddr _sockAddr; + SharedNodePointer _destinationNode; QByteArray _byteArray; }; diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index e357dd130e..474114697f 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -80,6 +80,37 @@ NodeList::~NodeList() { clear(); } +qint64 NodeList::writeDatagram(const QByteArray& datagram, const SharedNodePointer& destinationNode, + const HifiSockAddr& overridenSockAddr) { + + // setup the MD5 hash for source verification in the header + int numBytesPacketHeader = numBytesForPacketHeader(datagram); + QByteArray dataSecretHash = QCryptographicHash::hash(datagram.mid(numBytesPacketHeader) + + destinationNode->getConnectionSecret().toRfc4122(), + QCryptographicHash::Md5); + QByteArray datagramWithHash = datagram; + datagramWithHash.replace(numBytesPacketHeader - NUM_BYTES_MD5_HASH, NUM_BYTES_MD5_HASH, dataSecretHash); + + // if we don't have an ovveriden address, assume they want to send to the node's active socket + const HifiSockAddr* destinationSockAddr = &overridenSockAddr; + if (overridenSockAddr.isNull()) { + if (destinationNode->getActiveSocket()) { + // use the node's active socket as the destination socket + destinationSockAddr = destinationNode->getActiveSocket(); + } else { + // we don't have a socket to send to, return 0 + return 0; + } + } + + return _nodeSocket.writeDatagram(datagramWithHash, destinationSockAddr->getAddress(), destinationSockAddr->getPort()); +} + +qint64 NodeList::writeDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode, + const HifiSockAddr& overridenSockAddr) { + return writeDatagram(QByteArray(data, size), destinationNode, overridenSockAddr); +} + void NodeList::setDomainHostname(const QString& domainHostname) { if (domainHostname != _domainHostname) { diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index daac87da28..3710684dd8 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -76,6 +76,11 @@ public: void setSessionUUID(const QUuid& sessionUUID); QUdpSocket& getNodeSocket() { return _nodeSocket; } + + qint64 writeDatagram(const QByteArray& datagram, const SharedNodePointer& destinationNode, + const HifiSockAddr& overridenSockAddr = HifiSockAddr()); + qint64 writeDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode, + const HifiSockAddr& overridenSockAddr = HifiSockAddr()); void(*linkedDataCreateCallback)(Node *); diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index d350a8335c..99066cb66b 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -69,13 +69,20 @@ int populatePacketHeader(char* packet, PacketType type, const QUuid& connectionU int numTypeBytes = packArithmeticallyCodedValue(type, packet); packet[numTypeBytes] = versionForPacketType(type); + char* position = packet + numTypeBytes + sizeof(PacketVersion); + QUuid packUUID = connectionUUID.isNull() ? NodeList::getInstance()->getSessionUUID() : connectionUUID; QByteArray rfcUUID = packUUID.toRfc4122(); - memcpy(packet + numTypeBytes + sizeof(PacketVersion), rfcUUID.constData(), NUM_BYTES_RFC4122_UUID); + memcpy(position, rfcUUID.constData(), NUM_BYTES_RFC4122_UUID); + position += NUM_BYTES_RFC4122_UUID; + + // pack 16 bytes of zeros where the md5 hash will be placed one data is packed + memset(position, 0, NUM_BYTES_MD5_HASH); + position += NUM_BYTES_MD5_HASH; // return the number of bytes written for pointer pushing - return numTypeBytes + sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID; + return position - packet; } bool packetVersionMatch(const QByteArray& packet) { @@ -101,16 +108,16 @@ bool packetVersionMatch(const QByteArray& packet) { int numBytesForPacketHeader(const QByteArray& packet) { // returns the number of bytes used for the type, version, and UUID - return numBytesArithmeticCodingFromBuffer(packet.data()) + sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID; + return numBytesArithmeticCodingFromBuffer(packet.data()) + NUM_STATIC_HEADER_BYTES; } int numBytesForPacketHeader(const char* packet) { // returns the number of bytes used for the type, version, and UUID - return numBytesArithmeticCodingFromBuffer(packet) + sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID; + return numBytesArithmeticCodingFromBuffer(packet) + NUM_STATIC_HEADER_BYTES; } int numBytesForPacketHeaderGivenPacketType(PacketType type) { - return (int) ceilf((float)type / 255) + sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID; + return (int) ceilf((float)type / 255) + NUM_STATIC_HEADER_BYTES; } void deconstructPacketHeader(const QByteArray& packet, QUuid& senderUUID) { diff --git a/libraries/shared/src/PacketHeaders.h b/libraries/shared/src/PacketHeaders.h index 48d5175bd6..691dee861b 100644 --- a/libraries/shared/src/PacketHeaders.h +++ b/libraries/shared/src/PacketHeaders.h @@ -12,6 +12,7 @@ #ifndef hifi_PacketHeaders_h #define hifi_PacketHeaders_h +#include #include #include "UUID.h" @@ -57,7 +58,9 @@ enum PacketType { typedef char PacketVersion; -const int MAX_PACKET_HEADER_BYTES = sizeof(PacketType) + sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID;; +const int NUM_BYTES_MD5_HASH = 16; +const int NUM_STATIC_HEADER_BYTES = sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID + NUM_BYTES_MD5_HASH; +const int MAX_PACKET_HEADER_BYTES = sizeof(PacketType) + NUM_STATIC_HEADER_BYTES; PacketVersion versionForPacketType(PacketType type); diff --git a/libraries/shared/src/PacketSender.cpp b/libraries/shared/src/PacketSender.cpp index 8a031cbc39..9d819b96d7 100644 --- a/libraries/shared/src/PacketSender.cpp +++ b/libraries/shared/src/PacketSender.cpp @@ -47,8 +47,8 @@ PacketSender::~PacketSender() { } -void PacketSender::queuePacketForSending(const HifiSockAddr& address, const QByteArray& packet) { - NetworkPacket networkPacket(address, packet); +void PacketSender::queuePacketForSending(const SharedNodePointer& destinationNode, const QByteArray& packet) { + NetworkPacket networkPacket(destinationNode, packet); lock(); _packets.push_back(networkPacket); unlock(); @@ -263,9 +263,7 @@ bool PacketSender::nonThreadedProcess() { unlock(); // send the packet through the NodeList... - NodeList::getInstance()->getNodeSocket().writeDatagram(temporary.getByteArray(), - temporary.getSockAddr().getAddress(), - temporary.getSockAddr().getPort()); + NodeList::getInstance()->writeDatagram(temporary.getByteArray(), temporary.getDestinationNode()); packetsSentThisCall++; _packetsOverCheckInterval++; _totalPacketsSent++; diff --git a/libraries/shared/src/PacketSender.h b/libraries/shared/src/PacketSender.h index 4a1e62bd0c..9a14db5bda 100644 --- a/libraries/shared/src/PacketSender.h +++ b/libraries/shared/src/PacketSender.h @@ -37,7 +37,7 @@ public: /// \param packetData pointer to data /// \param ssize_t packetLength size of data /// \thread any thread, typically the application thread - void queuePacketForSending(const HifiSockAddr& address, const QByteArray& packet); + void queuePacketForSending(const SharedNodePointer& destinationNode, const QByteArray& packet); void setPacketsPerSecond(int packetsPerSecond); int getPacketsPerSecond() const { return _packetsPerSecond; } diff --git a/libraries/shared/src/ReceivedPacketProcessor.cpp b/libraries/shared/src/ReceivedPacketProcessor.cpp index 5faec02ea1..25c97faf4b 100644 --- a/libraries/shared/src/ReceivedPacketProcessor.cpp +++ b/libraries/shared/src/ReceivedPacketProcessor.cpp @@ -16,14 +16,11 @@ ReceivedPacketProcessor::ReceivedPacketProcessor() { _dontSleep = false; } -void ReceivedPacketProcessor::queueReceivedPacket(const HifiSockAddr& address, const QByteArray& packet) { +void ReceivedPacketProcessor::queueReceivedPacket(const SharedNodePointer& destinationNode, const QByteArray& packet) { // Make sure our Node and NodeList knows we've heard from this node. - SharedNodePointer node = NodeList::getInstance()->nodeWithAddress(address); - if (node) { - node->setLastHeardMicrostamp(usecTimestampNow()); - } + destinationNode->setLastHeardMicrostamp(usecTimestampNow()); - NetworkPacket networkPacket(address, packet); + NetworkPacket networkPacket(destinationNode, packet); lock(); _packets.push_back(networkPacket); unlock(); @@ -44,7 +41,8 @@ bool ReceivedPacketProcessor::process() { NetworkPacket temporary = packet; // make a copy of the packet in case the vector is resized on us _packets.erase(_packets.begin()); // remove the oldest packet unlock(); // let others add to the packets - processPacket(temporary.getSockAddr(), temporary.getByteArray()); // process our temporary copy + processPacket(*temporary.getDestinationNode()->getActiveSocket(), + temporary.getByteArray()); // process our temporary copy } return isStillRunning(); // keep running till they terminate us } diff --git a/libraries/shared/src/ReceivedPacketProcessor.h b/libraries/shared/src/ReceivedPacketProcessor.h index dfb4ed55a9..bd3e6a405a 100644 --- a/libraries/shared/src/ReceivedPacketProcessor.h +++ b/libraries/shared/src/ReceivedPacketProcessor.h @@ -24,7 +24,7 @@ public: /// \param packetData pointer to received data /// \param ssize_t packetLength size of received data /// \thread network receive thread - void queueReceivedPacket(const HifiSockAddr& senderSockAddr, const QByteArray& packet); + void queueReceivedPacket(const SharedNodePointer& destinationNode, const QByteArray& packet); /// Are there received packets waiting to be processed bool hasPacketsToProcess() const { return _packets.size() > 0; } From 97a7369c7603425b8845b157a07ab9c3aadbb38e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Feb 2014 14:43:46 -0800 Subject: [PATCH 20/42] remove senderWithAddress from NodeList --- .../octree/OctreeInboundPacketProcessor.cpp | 12 +++++------- .../src/octree/OctreeInboundPacketProcessor.h | 2 +- interface/src/Application.cpp | 18 ++++++++---------- interface/src/Application.h | 4 ++-- interface/src/DatagramProcessor.cpp | 8 ++++---- interface/src/VoxelPacketProcessor.cpp | 17 ++++++++--------- interface/src/VoxelPacketProcessor.h | 2 +- libraries/octree/src/JurisdictionListener.cpp | 15 ++++++--------- libraries/octree/src/JurisdictionListener.h | 2 +- libraries/octree/src/JurisdictionSender.cpp | 8 +++----- libraries/octree/src/JurisdictionSender.h | 2 +- libraries/shared/src/NodeList.cpp | 12 ------------ libraries/shared/src/NodeList.h | 1 - .../shared/src/ReceivedPacketProcessor.cpp | 3 +-- libraries/shared/src/ReceivedPacketProcessor.h | 2 +- 15 files changed, 42 insertions(+), 66 deletions(-) diff --git a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp index f9523851b4..1db3bfdc97 100644 --- a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp +++ b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp @@ -39,7 +39,7 @@ void OctreeInboundPacketProcessor::resetStats() { } -void OctreeInboundPacketProcessor::processPacket(const HifiSockAddr& senderSockAddr, const QByteArray& packet) { +void OctreeInboundPacketProcessor::processPacket(const SharedNodePointer& sendingNode, const QByteArray& packet) { bool debugProcessPacket = _myServer->wantsVerboseDebug(); @@ -55,8 +55,6 @@ void OctreeInboundPacketProcessor::processPacket(const HifiSockAddr& senderSockA if (_myServer->getOctree()->handlesEditPacketType(packetType)) { PerformanceWarning warn(debugProcessPacket, "processPacket KNOWN TYPE",debugProcessPacket); _receivedPacketCount++; - - SharedNodePointer senderNode = NodeList::getInstance()->nodeWithAddress(senderSockAddr); const unsigned char* packetData = reinterpret_cast(packet.data()); @@ -90,7 +88,7 @@ void OctreeInboundPacketProcessor::processPacket(const HifiSockAddr& senderSockA int editDataBytesRead = _myServer->getOctree()->processEditPacketData(packetType, reinterpret_cast(packet.data()), packet.size(), - editData, maxSize, senderNode.data()); + editData, maxSize, sendingNode.data()); _myServer->getOctree()->unlock(); quint64 endProcess = usecTimestampNow(); @@ -113,9 +111,9 @@ void OctreeInboundPacketProcessor::processPacket(const HifiSockAddr& senderSockA // Make sure our Node and NodeList knows we've heard from this node. QUuid& nodeUUID = DEFAULT_NODE_ID_REF; - if (senderNode) { - senderNode->setLastHeardMicrostamp(usecTimestampNow()); - nodeUUID = senderNode->getUUID(); + if (sendingNode) { + sendingNode->setLastHeardMicrostamp(usecTimestampNow()); + nodeUUID = sendingNode->getUUID(); if (debugProcessPacket) { qDebug() << "sender has uuid=" << nodeUUID; } diff --git a/assignment-client/src/octree/OctreeInboundPacketProcessor.h b/assignment-client/src/octree/OctreeInboundPacketProcessor.h index 3d9b12f484..237a22d954 100644 --- a/assignment-client/src/octree/OctreeInboundPacketProcessor.h +++ b/assignment-client/src/octree/OctreeInboundPacketProcessor.h @@ -63,7 +63,7 @@ public: NodeToSenderStatsMap& getSingleSenderStats() { return _singleSenderStats; } protected: - virtual void processPacket(const HifiSockAddr& senderSockAddr, const QByteArray& packet); + virtual void processPacket(const SharedNodePointer& sendingNode, const QByteArray& packet); private: void trackInboundPackets(const QUuid& nodeUUID, int sequence, quint64 transitTime, diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bd7f57d595..9a87137161 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3948,27 +3948,25 @@ void Application::nodeKilled(SharedNodePointer node) { } } -void Application::trackIncomingVoxelPacket(const QByteArray& packet, const HifiSockAddr& senderSockAddr, bool wasStatsPacket) { +void Application::trackIncomingVoxelPacket(const QByteArray& packet, const SharedNodePointer& sendingNode, bool wasStatsPacket) { // Attempt to identify the sender from it's address. - SharedNodePointer serverNode = NodeList::getInstance()->nodeWithAddress(senderSockAddr); - if (serverNode) { - QUuid nodeUUID = serverNode->getUUID(); + if (sendingNode) { + QUuid nodeUUID = sendingNode->getUUID(); // now that we know the node ID, let's add these stats to the stats for that node... _voxelSceneStatsLock.lockForWrite(); if (_octreeServerSceneStats.find(nodeUUID) != _octreeServerSceneStats.end()) { VoxelSceneStats& stats = _octreeServerSceneStats[nodeUUID]; - stats.trackIncomingOctreePacket(packet, wasStatsPacket, serverNode->getClockSkewUsec()); + stats.trackIncomingOctreePacket(packet, wasStatsPacket, sendingNode->getClockSkewUsec()); } _voxelSceneStatsLock.unlock(); } } -int Application::parseOctreeStats(const QByteArray& packet, const HifiSockAddr& senderSockAddr) { +int Application::parseOctreeStats(const QByteArray& packet, const SharedNodePointer& sendingNode) { // But, also identify the sender, and keep track of the contained jurisdiction root for this server - SharedNodePointer server = NodeList::getInstance()->nodeWithAddress(senderSockAddr); // parse the incoming stats datas stick it in a temporary object for now, while we // determine which server it belongs to @@ -3976,8 +3974,8 @@ int Application::parseOctreeStats(const QByteArray& packet, const HifiSockAddr& int statsMessageLength = temp.unpackFromMessage(reinterpret_cast(packet.data()), packet.size()); // quick fix for crash... why would voxelServer be NULL? - if (server) { - QUuid nodeUUID = server->getUUID(); + if (sendingNode) { + QUuid nodeUUID = sendingNode->getUUID(); // now that we know the node ID, let's add these stats to the stats for that node... _voxelSceneStatsLock.lockForWrite(); @@ -3994,7 +3992,7 @@ int Application::parseOctreeStats(const QByteArray& packet, const HifiSockAddr& // see if this is the first we've heard of this node... NodeToJurisdictionMap* jurisdiction = NULL; - if (server->getType() == NodeType::VoxelServer) { + if (sendingNode->getType() == NodeType::VoxelServer) { jurisdiction = &_voxelServerJurisdictions; } else { jurisdiction = &_particleServerJurisdictions; diff --git a/interface/src/Application.h b/interface/src/Application.h index d66bb8143e..93ca1c1608 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -470,8 +470,8 @@ private: PieMenu _pieMenu; - int parseOctreeStats(const QByteArray& packet, const HifiSockAddr& senderAddress); - void trackIncomingVoxelPacket(const QByteArray& packet, const HifiSockAddr& senderSockAddr, bool wasStatsPacket); + int parseOctreeStats(const QByteArray& packet, const SharedNodePointer& sendingNode); + void trackIncomingVoxelPacket(const QByteArray& packet, const SharedNodePointer& sendingNode, bool wasStatsPacket); NodeToJurisdictionMap _voxelServerJurisdictions; NodeToJurisdictionMap _particleServerJurisdictions; diff --git a/interface/src/DatagramProcessor.cpp b/interface/src/DatagramProcessor.cpp index f0cd2eb168..e3f46c52d4 100644 --- a/interface/src/DatagramProcessor.cpp +++ b/interface/src/DatagramProcessor.cpp @@ -40,6 +40,9 @@ void DatagramProcessor::processDatagrams() { _packetCount++; _byteCount += incomingPacket.size(); + QUuid nodeUUID; + deconstructPacketHeader(incomingPacket, nodeUUID); + if (packetVersionMatch(incomingPacket)) { // only process this packet if we have a match on the packet version switch (packetTypeForPacket(incomingPacket)) { @@ -84,9 +87,6 @@ void DatagramProcessor::processDatagrams() { printf("got PacketType_VOXEL_DATA, sequence:%d flightTime:%d\n", sequence, flightTime); } - QUuid nodeUUID; - deconstructPacketHeader(incomingPacket, nodeUUID); - SharedNodePointer matchedNode = NodeList::getInstance()->nodeWithUUID(nodeUUID); if (matchedNode) { @@ -103,7 +103,7 @@ void DatagramProcessor::processDatagrams() { case PacketTypeKillAvatar: case PacketTypeAvatarIdentity: { // update having heard from the avatar-mixer and record the bytes received - SharedNodePointer avatarMixer = NodeList::getInstance()->nodeWithAddress(senderSockAddr); + SharedNodePointer avatarMixer = nodeList->nodeWithUUID(nodeUUID); if (avatarMixer) { avatarMixer->setLastHeardMicrostamp(usecTimestampNow()); diff --git a/interface/src/VoxelPacketProcessor.cpp b/interface/src/VoxelPacketProcessor.cpp index bdb934430c..6404adbf42 100644 --- a/interface/src/VoxelPacketProcessor.cpp +++ b/interface/src/VoxelPacketProcessor.cpp @@ -14,7 +14,7 @@ #include "Menu.h" #include "VoxelPacketProcessor.h" -void VoxelPacketProcessor::processPacket(const HifiSockAddr& senderSockAddr, const QByteArray& packet) { +void VoxelPacketProcessor::processPacket(const SharedNodePointer& sendingNode, const QByteArray& packet) { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "VoxelPacketProcessor::processPacket()"); @@ -44,7 +44,7 @@ void VoxelPacketProcessor::processPacket(const HifiSockAddr& senderSockAddr, con // then process any remaining bytes as if it was another packet if (voxelPacketType == PacketTypeOctreeStats) { - int statsMessageLength = app->parseOctreeStats(mutablePacket, senderSockAddr); + int statsMessageLength = app->parseOctreeStats(mutablePacket, sendingNode); wasStatsPacket = true; if (messageLength > statsMessageLength) { mutablePacket = mutablePacket.mid(statsMessageLength); @@ -60,26 +60,25 @@ void VoxelPacketProcessor::processPacket(const HifiSockAddr& senderSockAddr, con voxelPacketType = packetTypeForPacket(mutablePacket); if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { - app->trackIncomingVoxelPacket(mutablePacket, senderSockAddr, wasStatsPacket); + app->trackIncomingVoxelPacket(mutablePacket, sendingNode, wasStatsPacket); - SharedNodePointer serverNode = NodeList::getInstance()->nodeWithAddress(senderSockAddr); - if (serverNode && serverNode->getActiveSocket() && *serverNode->getActiveSocket() == senderSockAddr) { + if (sendingNode) { switch(voxelPacketType) { case PacketTypeParticleErase: { - app->_particles.processEraseMessage(mutablePacket, senderSockAddr, serverNode.data()); + app->_particles.processEraseMessage(mutablePacket, *sendingNode->getActiveSocket(), sendingNode.data()); } break; case PacketTypeParticleData: { - app->_particles.processDatagram(mutablePacket, senderSockAddr, serverNode.data()); + app->_particles.processDatagram(mutablePacket, *sendingNode->getActiveSocket(), sendingNode.data()); } break; case PacketTypeEnvironmentData: { - app->_environment.parseData(senderSockAddr, mutablePacket); + app->_environment.parseData(*sendingNode->getActiveSocket(), mutablePacket); } break; default : { - app->_voxels.setDataSourceUUID(serverNode->getUUID()); + app->_voxels.setDataSourceUUID(sendingNode->getUUID()); app->_voxels.parseData(mutablePacket); app->_voxels.setDataSourceUUID(QUuid()); } break; diff --git a/interface/src/VoxelPacketProcessor.h b/interface/src/VoxelPacketProcessor.h index e0c3e9f542..42040fe446 100644 --- a/interface/src/VoxelPacketProcessor.h +++ b/interface/src/VoxelPacketProcessor.h @@ -17,6 +17,6 @@ /// the user is responsible for reading inbound packets and adding them to the processing queue by calling queueReceivedPacket() class VoxelPacketProcessor : public ReceivedPacketProcessor { protected: - virtual void processPacket(const HifiSockAddr& senderSockAddr, const QByteArray& packet); + virtual void processPacket(const SharedNodePointer& sendingNode, const QByteArray& packet); }; #endif // __shared__VoxelPacketProcessor__ diff --git a/libraries/octree/src/JurisdictionListener.cpp b/libraries/octree/src/JurisdictionListener.cpp index 4d17536313..fb364c7483 100644 --- a/libraries/octree/src/JurisdictionListener.cpp +++ b/libraries/octree/src/JurisdictionListener.cpp @@ -61,16 +61,13 @@ bool JurisdictionListener::queueJurisdictionRequest() { return isStillRunning(); } -void JurisdictionListener::processPacket(const HifiSockAddr& senderAddress, const QByteArray& packet) { +void JurisdictionListener::processPacket(const SharedNodePointer& sendingNode, const QByteArray& packet) { //qDebug() << "JurisdictionListener::processPacket()"; - if (packetTypeForPacket(packet) == PacketTypeJurisdictionRequest) { - SharedNodePointer node = NodeList::getInstance()->nodeWithAddress(senderAddress); - if (node) { - QUuid nodeUUID = node->getUUID(); - JurisdictionMap map; - map.unpackFromMessage(reinterpret_cast(packet.data()), packet.size()); - _jurisdictions[nodeUUID] = map; - } + if (packetTypeForPacket(packet) == PacketTypeJurisdictionRequest && sendingNode) { + QUuid nodeUUID = sendingNode->getUUID(); + JurisdictionMap map; + map.unpackFromMessage(reinterpret_cast(packet.data()), packet.size()); + _jurisdictions[nodeUUID] = map; } } diff --git a/libraries/octree/src/JurisdictionListener.h b/libraries/octree/src/JurisdictionListener.h index 712749aae7..b3dc9664d7 100644 --- a/libraries/octree/src/JurisdictionListener.h +++ b/libraries/octree/src/JurisdictionListener.h @@ -49,7 +49,7 @@ protected: /// \param packetData pointer to received data /// \param ssize_t packetLength size of received data /// \thread "this" individual processing thread - virtual void processPacket(const HifiSockAddr& senderAddress, const QByteArray& packet); + virtual void processPacket(const SharedNodePointer& sendingNode, const QByteArray& packet); private: NodeToJurisdictionMap _jurisdictions; diff --git a/libraries/octree/src/JurisdictionSender.cpp b/libraries/octree/src/JurisdictionSender.cpp index c540123a8c..49dddf75df 100644 --- a/libraries/octree/src/JurisdictionSender.cpp +++ b/libraries/octree/src/JurisdictionSender.cpp @@ -28,13 +28,11 @@ JurisdictionSender::~JurisdictionSender() { } -void JurisdictionSender::processPacket(const HifiSockAddr& senderAddress, const QByteArray& packet) { +void JurisdictionSender::processPacket(const SharedNodePointer& sendingNode, const QByteArray& packet) { if (packetTypeForPacket(packet) == PacketTypeJurisdictionRequest) { - QUuid nodeUUID; - deconstructPacketHeader(packet, nodeUUID); - if (!nodeUUID.isNull()) { + if (sendingNode) { lockRequestingNodes(); - _nodesRequestingJurisdictions.push(nodeUUID); + _nodesRequestingJurisdictions.push(sendingNode->getUUID()); unlockRequestingNodes(); } } diff --git a/libraries/octree/src/JurisdictionSender.h b/libraries/octree/src/JurisdictionSender.h index 19ce727a57..18365fda63 100644 --- a/libraries/octree/src/JurisdictionSender.h +++ b/libraries/octree/src/JurisdictionSender.h @@ -37,7 +37,7 @@ public: void setNodeType(NodeType_t type) { _nodeType = type; } protected: - virtual void processPacket(const HifiSockAddr& senderAddress, const QByteArray& packet); + virtual void processPacket(const SharedNodePointer& sendingNode, const QByteArray& packet); /// Locks all the resources of the thread. void lockRequestingNodes() { _requestingNodeMutex.lock(); } diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 474114697f..1810acb6f8 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -246,18 +246,6 @@ int NodeList::updateNodeWithData(Node *node, const HifiSockAddr& senderSockAddr, } } -SharedNodePointer NodeList::nodeWithAddress(const HifiSockAddr &senderSockAddr) { - // naively returns the first node that has a matching active HifiSockAddr - // note that there can be multiple nodes that have a matching active socket, so this isn't a good way to uniquely identify - foreach (const SharedNodePointer& node, getNodeHash()) { - if (node->getActiveSocket() && *node->getActiveSocket() == senderSockAddr) { - return node; - } - } - - return SharedNodePointer(); -} - SharedNodePointer NodeList::nodeWithUUID(const QUuid& nodeUUID) { QMutexLocker locker(&_nodeHashMutex); return _nodeHash.value(nodeUUID); diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 3710684dd8..d3c3dfcbac 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -104,7 +104,6 @@ public: QByteArray constructPingReplyPacket(const QByteArray& pingPacket); void pingPublicAndLocalSocketsForInactiveNode(Node* node); - SharedNodePointer nodeWithAddress(const HifiSockAddr& senderSockAddr); SharedNodePointer nodeWithUUID(const QUuid& nodeUUID); SharedNodePointer addOrUpdateNode(const QUuid& uuid, char nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket); diff --git a/libraries/shared/src/ReceivedPacketProcessor.cpp b/libraries/shared/src/ReceivedPacketProcessor.cpp index 25c97faf4b..b966109903 100644 --- a/libraries/shared/src/ReceivedPacketProcessor.cpp +++ b/libraries/shared/src/ReceivedPacketProcessor.cpp @@ -41,8 +41,7 @@ bool ReceivedPacketProcessor::process() { NetworkPacket temporary = packet; // make a copy of the packet in case the vector is resized on us _packets.erase(_packets.begin()); // remove the oldest packet unlock(); // let others add to the packets - processPacket(*temporary.getDestinationNode()->getActiveSocket(), - temporary.getByteArray()); // process our temporary copy + processPacket(temporary.getDestinationNode(), temporary.getByteArray()); // process our temporary copy } return isStillRunning(); // keep running till they terminate us } diff --git a/libraries/shared/src/ReceivedPacketProcessor.h b/libraries/shared/src/ReceivedPacketProcessor.h index bd3e6a405a..043dd6c6c4 100644 --- a/libraries/shared/src/ReceivedPacketProcessor.h +++ b/libraries/shared/src/ReceivedPacketProcessor.h @@ -38,7 +38,7 @@ protected: /// \param packetData pointer to received data /// \param ssize_t packetLength size of received data /// \thread "this" individual processing thread - virtual void processPacket(const HifiSockAddr& senderAddress, const QByteArray& packet) = 0; + virtual void processPacket(const SharedNodePointer& sendingNode, const QByteArray& packet) = 0; /// Implements generic processing behavior for this thread. virtual bool process(); From c1132726bfa50b772bfad10dde7dcd875e1cfb98 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Feb 2014 14:58:03 -0800 Subject: [PATCH 21/42] use SharedNodePointer in place of Node where appropriate --- .../src/octree/OctreeInboundPacketProcessor.cpp | 2 +- assignment-client/src/octree/OctreeSendThread.cpp | 6 +++--- assignment-client/src/octree/OctreeSendThread.h | 4 ++-- assignment-client/src/octree/OctreeServer.h | 4 ++-- assignment-client/src/particles/ParticleServer.cpp | 8 ++++---- assignment-client/src/particles/ParticleServer.h | 6 +++--- assignment-client/src/voxels/VoxelServer.cpp | 4 ++-- assignment-client/src/voxels/VoxelServer.h | 4 ++-- interface/src/ParticleTreeRenderer.cpp | 5 ++--- interface/src/ParticleTreeRenderer.h | 2 +- interface/src/VoxelPacketProcessor.cpp | 4 ++-- libraries/octree/src/Octree.cpp | 4 ++-- libraries/octree/src/Octree.h | 6 +++--- libraries/octree/src/OctreeRenderer.cpp | 2 +- libraries/octree/src/OctreeRenderer.h | 2 +- libraries/particles/src/ParticleTree.cpp | 11 +++++------ libraries/particles/src/ParticleTree.h | 10 +++++----- libraries/particles/src/ParticleTreeElement.cpp | 2 +- libraries/particles/src/ParticleTreeElement.h | 2 +- libraries/voxels/src/VoxelTree.cpp | 2 +- libraries/voxels/src/VoxelTree.h | 2 +- 21 files changed, 45 insertions(+), 47 deletions(-) diff --git a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp index 1db3bfdc97..5e8de3a1b3 100644 --- a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp +++ b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp @@ -88,7 +88,7 @@ void OctreeInboundPacketProcessor::processPacket(const SharedNodePointer& sendin int editDataBytesRead = _myServer->getOctree()->processEditPacketData(packetType, reinterpret_cast(packet.data()), packet.size(), - editData, maxSize, sendingNode.data()); + editData, maxSize, sendingNode); _myServer->getOctree()->unlock(); quint64 endProcess = usecTimestampNow(); diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 5672cd7cac..121e80b808 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -48,7 +48,7 @@ bool OctreeSendThread::process() { if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) { printf("nodeData->updateCurrentViewFrustum() changed=%s\n", debug::valueOf(viewFrustumChanged)); } - packetsSent = packetDistributor(node.data(), nodeData, viewFrustumChanged); + packetsSent = packetDistributor(node, nodeData, viewFrustumChanged); } node->getMutex().unlock(); // we're done with this node for now. @@ -86,7 +86,7 @@ quint64 OctreeSendThread::_totalBytes = 0; quint64 OctreeSendThread::_totalWastedBytes = 0; quint64 OctreeSendThread::_totalPackets = 0; -int OctreeSendThread::handlePacketSend(Node* node, OctreeQueryNode* nodeData, int& trueBytesSent, int& truePacketsSent) { +int OctreeSendThread::handlePacketSend(const SharedNodePointer& node, OctreeQueryNode* nodeData, int& trueBytesSent, int& truePacketsSent) { bool debug = _myServer->wantsDebugSending(); quint64 now = usecTimestampNow(); @@ -212,7 +212,7 @@ int OctreeSendThread::handlePacketSend(Node* node, OctreeQueryNode* nodeData, in } /// Version of voxel distributor that sends the deepest LOD level at once -int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, bool viewFrustumChanged) { +int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQueryNode* nodeData, bool viewFrustumChanged) { bool forceDebugging = false; int truePacketsSent = 0; diff --git a/assignment-client/src/octree/OctreeSendThread.h b/assignment-client/src/octree/OctreeSendThread.h index 6f60f0eb41..ab7a7231ab 100644 --- a/assignment-client/src/octree/OctreeSendThread.h +++ b/assignment-client/src/octree/OctreeSendThread.h @@ -36,8 +36,8 @@ private: QUuid _nodeUUID; OctreeServer* _myServer; - int handlePacketSend(Node* node, OctreeQueryNode* nodeData, int& trueBytesSent, int& truePacketsSent); - int packetDistributor(Node* node, OctreeQueryNode* nodeData, bool viewFrustumChanged); + int handlePacketSend(const SharedNodePointer& node, OctreeQueryNode* nodeData, int& trueBytesSent, int& truePacketsSent); + int packetDistributor(const SharedNodePointer& node, OctreeQueryNode* nodeData, bool viewFrustumChanged); OctreePacketData _packetData; }; diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index 48a74a5e9e..26c39d1a1d 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -58,8 +58,8 @@ public: // subclass may implement these method virtual void beforeRun() { }; - virtual bool hasSpecialPacketToSend(Node* node) { return false; } - virtual int sendSpecialPacket(Node* node) { return 0; } + virtual bool hasSpecialPacketToSend(const SharedNodePointer& node) { return false; } + virtual int sendSpecialPacket(const SharedNodePointer& node) { return 0; } static void attachQueryNodeToNode(Node* newNode); diff --git a/assignment-client/src/particles/ParticleServer.cpp b/assignment-client/src/particles/ParticleServer.cpp index db546f5960..1785ef46d6 100644 --- a/assignment-client/src/particles/ParticleServer.cpp +++ b/assignment-client/src/particles/ParticleServer.cpp @@ -43,7 +43,7 @@ void ParticleServer::beforeRun() { pruneDeletedParticlesTimer->start(PRUNE_DELETED_PARTICLES_INTERVAL_MSECS); } -void ParticleServer::particleCreated(const Particle& newParticle, Node* node) { +void ParticleServer::particleCreated(const Particle& newParticle, const SharedNodePointer& senderNode) { unsigned char outputBuffer[MAX_PACKET_SIZE]; unsigned char* copyAt = outputBuffer; @@ -63,12 +63,12 @@ void ParticleServer::particleCreated(const Particle& newParticle, Node* node) { copyAt += sizeof(particleID); packetLength += sizeof(particleID); - NodeList::getInstance()->writeDatagram((char*) outputBuffer, packetLength, SharedNodePointer(node)); + NodeList::getInstance()->writeDatagram((char*) outputBuffer, packetLength, senderNode); } // ParticleServer will use the "special packets" to send list of recently deleted particles -bool ParticleServer::hasSpecialPacketToSend(Node* node) { +bool ParticleServer::hasSpecialPacketToSend(const SharedNodePointer& node) { bool shouldSendDeletedParticles = false; // check to see if any new particles have been added since we last sent to this node... @@ -83,7 +83,7 @@ bool ParticleServer::hasSpecialPacketToSend(Node* node) { return shouldSendDeletedParticles; } -int ParticleServer::sendSpecialPacket(Node* node) { +int ParticleServer::sendSpecialPacket(const SharedNodePointer& node) { unsigned char outputBuffer[MAX_PACKET_SIZE]; size_t packetLength = 0; diff --git a/assignment-client/src/particles/ParticleServer.h b/assignment-client/src/particles/ParticleServer.h index 345ebe86e3..4e6a896475 100644 --- a/assignment-client/src/particles/ParticleServer.h +++ b/assignment-client/src/particles/ParticleServer.h @@ -34,10 +34,10 @@ public: // subclass may implement these method virtual void beforeRun(); - virtual bool hasSpecialPacketToSend(Node* node); - virtual int sendSpecialPacket(Node* node); + virtual bool hasSpecialPacketToSend(const SharedNodePointer& node); + virtual int sendSpecialPacket(const SharedNodePointer& node); - virtual void particleCreated(const Particle& newParticle, Node* senderNode); + virtual void particleCreated(const Particle& newParticle, const SharedNodePointer& senderNode); public slots: void pruneDeletedParticles(); diff --git a/assignment-client/src/voxels/VoxelServer.cpp b/assignment-client/src/voxels/VoxelServer.cpp index 1edec370bc..771c91570f 100644 --- a/assignment-client/src/voxels/VoxelServer.cpp +++ b/assignment-client/src/voxels/VoxelServer.cpp @@ -32,12 +32,12 @@ Octree* VoxelServer::createTree() { return new VoxelTree(true); } -bool VoxelServer::hasSpecialPacketToSend(Node* node) { +bool VoxelServer::hasSpecialPacketToSend(const SharedNodePointer& node) { bool shouldSendEnvironments = _sendEnvironments && shouldDo(ENVIRONMENT_SEND_INTERVAL_USECS, OCTREE_SEND_INTERVAL_USECS); return shouldSendEnvironments; } -int VoxelServer::sendSpecialPacket(Node* node) { +int VoxelServer::sendSpecialPacket(const SharedNodePointer& node) { int numBytesPacketHeader = populatePacketHeader(reinterpret_cast(_tempOutputBuffer), PacketTypeEnvironmentData); int envPacketLength = numBytesPacketHeader; int environmentsToSend = getSendMinimalEnvironment() ? 1 : getEnvironmentDataCount(); diff --git a/assignment-client/src/voxels/VoxelServer.h b/assignment-client/src/voxels/VoxelServer.h index 526a3b2c54..509d838fff 100644 --- a/assignment-client/src/voxels/VoxelServer.h +++ b/assignment-client/src/voxels/VoxelServer.h @@ -43,8 +43,8 @@ public: // subclass may implement these method virtual void beforeRun(); - virtual bool hasSpecialPacketToSend(Node* node); - virtual int sendSpecialPacket(Node* node); + virtual bool hasSpecialPacketToSend(const SharedNodePointer& node); + virtual int sendSpecialPacket(const SharedNodePointer& node); private: diff --git a/interface/src/ParticleTreeRenderer.cpp b/interface/src/ParticleTreeRenderer.cpp index 7a1991ca93..d9d0849c94 100644 --- a/interface/src/ParticleTreeRenderer.cpp +++ b/interface/src/ParticleTreeRenderer.cpp @@ -123,7 +123,6 @@ void ParticleTreeRenderer::renderElement(OctreeElement* element, RenderArgs* arg } } -void ParticleTreeRenderer::processEraseMessage(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr, - Node* sourceNode) { - static_cast(_tree)->processEraseMessage(dataByteArray, senderSockAddr, sourceNode); +void ParticleTreeRenderer::processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) { + static_cast(_tree)->processEraseMessage(dataByteArray, sourceNode); } diff --git a/interface/src/ParticleTreeRenderer.h b/interface/src/ParticleTreeRenderer.h index 48b15f9c67..fe346ae730 100644 --- a/interface/src/ParticleTreeRenderer.h +++ b/interface/src/ParticleTreeRenderer.h @@ -38,7 +38,7 @@ public: ParticleTree* getTree() { return (ParticleTree*)_tree; } - void processEraseMessage(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr, Node* sourceNode); + void processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode); virtual void init(); virtual void render(); diff --git a/interface/src/VoxelPacketProcessor.cpp b/interface/src/VoxelPacketProcessor.cpp index 6404adbf42..b5ec4247f2 100644 --- a/interface/src/VoxelPacketProcessor.cpp +++ b/interface/src/VoxelPacketProcessor.cpp @@ -66,11 +66,11 @@ void VoxelPacketProcessor::processPacket(const SharedNodePointer& sendingNode, c switch(voxelPacketType) { case PacketTypeParticleErase: { - app->_particles.processEraseMessage(mutablePacket, *sendingNode->getActiveSocket(), sendingNode.data()); + app->_particles.processEraseMessage(mutablePacket, sendingNode); } break; case PacketTypeParticleData: { - app->_particles.processDatagram(mutablePacket, *sendingNode->getActiveSocket(), sendingNode.data()); + app->_particles.processDatagram(mutablePacket, sendingNode); } break; case PacketTypeEnvironmentData: { diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 93ce5c9174..5a1e31e0d0 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -1347,7 +1347,7 @@ bool Octree::readFromSVOFile(const char* fileName) { fileOk = true; // assume the file is ok } if (fileOk) { - ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS, NULL, 0, NULL, wantImportProgress); + ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS, NULL, 0, SharedNodePointer(), wantImportProgress); readBitstreamToTree(dataAt, dataLength, args); } delete[] entireFile; @@ -1485,7 +1485,7 @@ void Octree::copyFromTreeIntoSubTree(Octree* sourceTree, OctreeElement* destinat // ask destination tree to read the bitstream bool wantImportProgress = true; - ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS, destinationNode, 0, NULL, wantImportProgress); + ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS, destinationNode, 0, SharedNodePointer(), wantImportProgress); readBitstreamToTree(packetData.getUncompressedData(), packetData.getUncompressedSize(), args); } } diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 9b8921208b..5287e3ce37 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -156,7 +156,7 @@ public: bool includeExistsBits; OctreeElement* destinationNode; QUuid sourceUUID; - Node* sourceNode; + SharedNodePointer sourceNode; bool wantImportProgress; ReadBitstreamToTreeParams( @@ -164,7 +164,7 @@ public: bool includeExistsBits = WANT_EXISTS_BITS, OctreeElement* destinationNode = NULL, QUuid sourceUUID = QUuid(), - Node* sourceNode = NULL, + SharedNodePointer sourceNode = SharedNodePointer(), bool wantImportProgress = false) : includeColor(includeColor), includeExistsBits(includeExistsBits), @@ -190,7 +190,7 @@ public: virtual PacketType expectedDataPacketType() const { return PacketTypeUnknown; } virtual bool handlesEditPacketType(PacketType packetType) const { return false; } virtual int processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength, - const unsigned char* editData, int maxLength, Node* senderNode) { return 0; } + const unsigned char* editData, int maxLength, const SharedNodePointer& sourceNode) { return 0; } virtual void update() { }; // nothing to do by default diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index b636d9baac..9a00ce245b 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -26,7 +26,7 @@ void OctreeRenderer::init() { OctreeRenderer::~OctreeRenderer() { } -void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr, Node* sourceNode) { +void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) { bool showTimingDetails = false; // Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); bool extraDebugging = false; // Menu::getInstance()->isOptionChecked(MenuOption::ExtraDebugging) PerformanceWarning warn(showTimingDetails, "OctreeRenderer::processDatagram()",showTimingDetails); diff --git a/libraries/octree/src/OctreeRenderer.h b/libraries/octree/src/OctreeRenderer.h index ff385ec62d..e29cdc4020 100644 --- a/libraries/octree/src/OctreeRenderer.h +++ b/libraries/octree/src/OctreeRenderer.h @@ -43,7 +43,7 @@ public: virtual void renderElement(OctreeElement* element, RenderArgs* args) = 0; /// process incoming data - virtual void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr, Node* sourceNode); + virtual void processDatagram(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode); /// initialize and GPU/rendering related resources virtual void init(); diff --git a/libraries/particles/src/ParticleTree.cpp b/libraries/particles/src/ParticleTree.cpp index 51150722d0..afffe7943c 100644 --- a/libraries/particles/src/ParticleTree.cpp +++ b/libraries/particles/src/ParticleTree.cpp @@ -90,7 +90,7 @@ bool ParticleTree::findAndUpdateOperation(OctreeElement* element, void* extraDat return true; } -void ParticleTree::storeParticle(const Particle& particle, Node* senderNode) { +void ParticleTree::storeParticle(const Particle& particle, const SharedNodePointer& senderNode) { // First, look for the existing particle in the tree.. FindAndUpdateParticleArgs args = { particle, false }; recurseTreeWithOperation(findAndUpdateOperation, &args); @@ -101,7 +101,7 @@ void ParticleTree::storeParticle(const Particle& particle, Node* senderNode) { float size = std::max(MINIMUM_PARTICLE_ELEMENT_SIZE, particle.getRadius()); ParticleTreeElement* element = (ParticleTreeElement*)getOrCreateChildElementAt(position.x, position.y, position.z, size); - element->storeParticle(particle, senderNode); + element->storeParticle(particle); } // what else do we need to do here to get reaveraging to work _isDirty = true; @@ -386,7 +386,7 @@ const Particle* ParticleTree::findParticleByID(uint32_t id, bool alreadyLocked) int ParticleTree::processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength, - const unsigned char* editData, int maxLength, Node* senderNode) { + const unsigned char* editData, int maxLength, const SharedNodePointer& senderNode) { int processedBytes = 0; // we handle these types of "edit" packets @@ -415,7 +415,7 @@ int ParticleTree::processEditPacketData(PacketType packetType, const unsigned ch return processedBytes; } -void ParticleTree::notifyNewlyCreatedParticle(const Particle& newParticle, Node* senderNode) { +void ParticleTree::notifyNewlyCreatedParticle(const Particle& newParticle, const SharedNodePointer& senderNode) { _newlyCreatedHooksLock.lockForRead(); for (size_t i = 0; i < _newlyCreatedHooks.size(); i++) { _newlyCreatedHooks[i]->particleCreated(newParticle, senderNode); @@ -596,8 +596,7 @@ void ParticleTree::forgetParticlesDeletedBefore(quint64 sinceTime) { } -void ParticleTree::processEraseMessage(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr, - Node* sourceNode) { +void ParticleTree::processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) { const unsigned char* packetData = (const unsigned char*)dataByteArray.constData(); const unsigned char* dataAt = packetData; diff --git a/libraries/particles/src/ParticleTree.h b/libraries/particles/src/ParticleTree.h index e3b7906778..f3b8f5183d 100644 --- a/libraries/particles/src/ParticleTree.h +++ b/libraries/particles/src/ParticleTree.h @@ -14,7 +14,7 @@ class NewlyCreatedParticleHook { public: - virtual void particleCreated(const Particle& newParticle, Node* senderNode) = 0; + virtual void particleCreated(const Particle& newParticle, const SharedNodePointer& senderNode) = 0; }; class ParticleTree : public Octree { @@ -35,11 +35,11 @@ public: virtual PacketType expectedDataPacketType() const { return PacketTypeParticleData; } virtual bool handlesEditPacketType(PacketType packetType) const; virtual int processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength, - const unsigned char* editData, int maxLength, Node* senderNode); + const unsigned char* editData, int maxLength, const SharedNodePointer& senderNode); virtual void update(); - void storeParticle(const Particle& particle, Node* senderNode = NULL); + void storeParticle(const Particle& particle, const SharedNodePointer& senderNode = SharedNodePointer()); void updateParticle(const ParticleID& particleID, const ParticleProperties& properties); void addParticle(const ParticleID& particleID, const ParticleProperties& properties); void deleteParticle(const ParticleID& particleID); @@ -67,7 +67,7 @@ public: bool encodeParticlesDeletedSince(quint64& sinceTime, unsigned char* packetData, size_t maxLength, size_t& outputLength); void forgetParticlesDeletedBefore(quint64 sinceTime); - void processEraseMessage(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr, Node* sourceNode); + void processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode); void handleAddParticleResponse(const QByteArray& packet); private: @@ -82,7 +82,7 @@ private: static bool findAndDeleteOperation(OctreeElement* element, void* extraData); static bool findAndUpdateParticleIDOperation(OctreeElement* element, void* extraData); - void notifyNewlyCreatedParticle(const Particle& newParticle, Node* senderNode); + void notifyNewlyCreatedParticle(const Particle& newParticle, const SharedNodePointer& senderNode); QReadWriteLock _newlyCreatedHooksLock; std::vector _newlyCreatedHooks; diff --git a/libraries/particles/src/ParticleTreeElement.cpp b/libraries/particles/src/ParticleTreeElement.cpp index 48e619da59..4930263d64 100644 --- a/libraries/particles/src/ParticleTreeElement.cpp +++ b/libraries/particles/src/ParticleTreeElement.cpp @@ -332,7 +332,7 @@ bool ParticleTreeElement::collapseChildren() { } -void ParticleTreeElement::storeParticle(const Particle& particle, Node* senderNode) { +void ParticleTreeElement::storeParticle(const Particle& particle) { _particles->push_back(particle); markWithChangedTime(); } diff --git a/libraries/particles/src/ParticleTreeElement.h b/libraries/particles/src/ParticleTreeElement.h index 59a03f7b41..2854066f3b 100644 --- a/libraries/particles/src/ParticleTreeElement.h +++ b/libraries/particles/src/ParticleTreeElement.h @@ -121,7 +121,7 @@ public: protected: virtual void init(unsigned char * octalCode); - void storeParticle(const Particle& particle, Node* senderNode = NULL); + void storeParticle(const Particle& particle); ParticleTree* _myTree; QList* _particles; diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 90fdbb8a05..e29cfda41d 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -522,7 +522,7 @@ bool VoxelTree::handlesEditPacketType(PacketType packetType) const { } int VoxelTree::processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength, - const unsigned char* editData, int maxLength, Node* senderNode) { + const unsigned char* editData, int maxLength, const SharedNodePointer& node) { // we handle these types of "edit" packets switch (packetType) { diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index 4f30293766..b5f28811fc 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -54,7 +54,7 @@ public: virtual PacketType expectedDataPacketType() const { return PacketTypeVoxelData; } virtual bool handlesEditPacketType(PacketType packetType) const; virtual int processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength, - const unsigned char* editData, int maxLength, Node* senderNode); + const unsigned char* editData, int maxLength, const SharedNodePointer& node); void processSetVoxelsBitstream(const unsigned char* bitstream, int bufferSizeBytes); /** From b988308a8d4e3e13aaf535b9fdc2555edf550f3b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 7 Feb 2014 09:49:54 -0800 Subject: [PATCH 22/42] leverage writeDatagram helper in NodeList, ping if no active socket --- interface/src/Audio.cpp | 2 +- interface/src/ui/VoxelStatsDialog.cpp | 2 +- libraries/audio/src/AudioInjector.cpp | 8 +++-- libraries/octree/src/JurisdictionListener.cpp | 2 +- .../octree/src/OctreeEditPacketSender.cpp | 4 +-- libraries/shared/src/NodeList.cpp | 36 +++++++++++-------- libraries/shared/src/NodeList.h | 7 ++-- 7 files changed, 35 insertions(+), 26 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 4acda2fe9b..e7fdcd32c7 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -388,7 +388,7 @@ void Audio::handleAudioInput() { NodeList* nodeList = NodeList::getInstance(); SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer); - if (audioMixer && nodeList->getNodeActiveSocketOrPing(audioMixer.data())) { + if (audioMixer && nodeList->getNodeActiveSocketOrPing(audioMixer)) { MyAvatar* interfaceAvatar = Application::getInstance()->getAvatar(); glm::vec3 headPosition = interfaceAvatar->getHead().getPosition(); glm::quat headOrientation = interfaceAvatar->getHead().getOrientation(); diff --git a/interface/src/ui/VoxelStatsDialog.cpp b/interface/src/ui/VoxelStatsDialog.cpp index 27b7f788ec..1d94705504 100644 --- a/interface/src/ui/VoxelStatsDialog.cpp +++ b/interface/src/ui/VoxelStatsDialog.cpp @@ -265,7 +265,7 @@ void VoxelStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t serv std::stringstream extraDetails(""); std::stringstream linkDetails(""); - if (nodeList->getNodeActiveSocketOrPing(node.data())) { + if (nodeList->getNodeActiveSocketOrPing(node)) { serverDetails << "active "; } else { serverDetails << "inactive "; diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 6dd7342eba..905c1ecfc6 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -93,9 +93,11 @@ void AudioInjector::injectAudio() { // grab our audio mixer from the NodeList, if it exists SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer); - if (audioMixer && nodeList->getNodeActiveSocketOrPing(audioMixer.data())) { - // send off this audio packet - nodeList->writeDatagram(injectAudioPacket, audioMixer); + // send off this audio packet + nodeList->writeDatagram(injectAudioPacket, audioMixer); + + if (audioMixer && nodeList->getNodeActiveSocketOrPing(audioMixer)) { + } currentSendPosition += bytesToCopy; diff --git a/libraries/octree/src/JurisdictionListener.cpp b/libraries/octree/src/JurisdictionListener.cpp index fb364c7483..a15c72cc5e 100644 --- a/libraries/octree/src/JurisdictionListener.cpp +++ b/libraries/octree/src/JurisdictionListener.cpp @@ -45,7 +45,7 @@ bool JurisdictionListener::queueJurisdictionRequest() { NodeList* nodeList = NodeList::getInstance(); foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { - if (nodeList->getNodeActiveSocketOrPing(node.data()) && node->getType() == getNodeType()) { + if (nodeList->getNodeActiveSocketOrPing(node) && node->getType() == getNodeType()) { _packetSender.queuePacketForSending(node, QByteArray(reinterpret_cast(bufferOut), sizeOut)); nodeCount++; } diff --git a/libraries/octree/src/OctreeEditPacketSender.cpp b/libraries/octree/src/OctreeEditPacketSender.cpp index f7b60b3d3f..ca3ffc707f 100644 --- a/libraries/octree/src/OctreeEditPacketSender.cpp +++ b/libraries/octree/src/OctreeEditPacketSender.cpp @@ -61,7 +61,7 @@ bool OctreeEditPacketSender::serversExist() const { foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { // only send to the NodeTypes that are getMyNodeType() if (node->getType() == getMyNodeType()) { - if (nodeList->getNodeActiveSocketOrPing(node.data())) { + if (nodeList->getNodeActiveSocketOrPing(node)) { QUuid nodeUUID = node->getUUID(); // If we've got Jurisdictions set, then check to see if we know the jurisdiction for this server if (_serverJurisdictions) { @@ -91,7 +91,7 @@ void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned c // only send to the NodeTypes that are getMyNodeType() if (node->getType() == getMyNodeType() && ((node->getUUID() == nodeUUID) || (nodeUUID.isNull()))) { - if (nodeList->getNodeActiveSocketOrPing(node.data())) { + if (nodeList->getNodeActiveSocketOrPing(node)) { queuePacketForSending(node, QByteArray(reinterpret_cast(buffer), length)); // debugging output... diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 1810acb6f8..6b9ef4f406 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -94,7 +94,7 @@ qint64 NodeList::writeDatagram(const QByteArray& datagram, const SharedNodePoint // if we don't have an ovveriden address, assume they want to send to the node's active socket const HifiSockAddr* destinationSockAddr = &overridenSockAddr; if (overridenSockAddr.isNull()) { - if (destinationNode->getActiveSocket()) { + if (getNodeActiveSocketOrPing(destinationNode)) { // use the node's active socket as the destination socket destinationSockAddr = destinationNode->getActiveSocket(); } else { @@ -196,7 +196,7 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr case PacketTypePing: { // send back a reply QByteArray replyPacket = constructPingReplyPacket(packet); - _nodeSocket.writeDatagram(replyPacket, senderSockAddr.getAddress(), senderSockAddr.getPort()); + writeDatagram(replyPacket, sendingNodeForPacket(packet), senderSockAddr); break; } case PacketTypePingReply: { @@ -251,6 +251,14 @@ SharedNodePointer NodeList::nodeWithUUID(const QUuid& nodeUUID) { return _nodeHash.value(nodeUUID); } +SharedNodePointer NodeList::sendingNodeForPacket(const QByteArray& packet) { + QUuid nodeUUID; + deconstructPacketHeader(packet, nodeUUID); + + // return the matching node, or NULL if there is no match + return nodeWithUUID(nodeUUID); +} + NodeHash NodeList::getNodeHash() { QMutexLocker locker(&_nodeHashMutex); return NodeHash(_nodeHash); @@ -606,12 +614,12 @@ QByteArray NodeList::constructPingReplyPacket(const QByteArray& pingPacket) { return replyPacket; } -void NodeList::pingPublicAndLocalSocketsForInactiveNode(Node* node) { +void NodeList::pingPublicAndLocalSocketsForInactiveNode(const SharedNodePointer& node) { QByteArray pingPacket = constructPingPacket(); // send the ping packet to the local and public sockets for this node - _nodeSocket.writeDatagram(pingPacket, node->getLocalSocket().getAddress(), node->getLocalSocket().getPort()); - _nodeSocket.writeDatagram(pingPacket, node->getPublicSocket().getAddress(), node->getPublicSocket().getPort()); + writeDatagram(pingPacket, node); + writeDatagram(pingPacket, node); } SharedNodePointer NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, @@ -668,11 +676,8 @@ unsigned NodeList::broadcastToNodes(const QByteArray& packet, const NodeSet& des foreach (const SharedNodePointer& node, getNodeHash()) { // only send to the NodeTypes we are asked to send to. if (destinationNodeTypes.contains(node->getType())) { - if (getNodeActiveSocketOrPing(node.data())) { - // we know which socket is good for this node, send there - _nodeSocket.writeDatagram(packet, node->getActiveSocket()->getAddress(), node->getActiveSocket()->getPort()); - ++n; - } + writeDatagram(packet, node); + ++n; } } @@ -683,18 +688,19 @@ void NodeList::pingInactiveNodes() { foreach (const SharedNodePointer& node, getNodeHash()) { if (!node->getActiveSocket()) { // we don't have an active link to this node, ping it to set that up - pingPublicAndLocalSocketsForInactiveNode(node.data()); + pingPublicAndLocalSocketsForInactiveNode(node); } } } -const HifiSockAddr* NodeList::getNodeActiveSocketOrPing(Node* node) { - if (node->getActiveSocket()) { +const HifiSockAddr* NodeList::getNodeActiveSocketOrPing(const SharedNodePointer& node) { + if (node && node->getActiveSocket()) { return node->getActiveSocket(); - } else { + } else if (node) { pingPublicAndLocalSocketsForInactiveNode(node); - return NULL; } + + return NULL; } void NodeList::activateSocketFromNodeCommunication(const HifiSockAddr& nodeAddress) { diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index d3c3dfcbac..1a035e91d1 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -102,10 +102,11 @@ public: QByteArray constructPingPacket(); QByteArray constructPingReplyPacket(const QByteArray& pingPacket); - void pingPublicAndLocalSocketsForInactiveNode(Node* node); + void pingPublicAndLocalSocketsForInactiveNode(const SharedNodePointer& node); SharedNodePointer nodeWithUUID(const QUuid& nodeUUID); - + SharedNodePointer sendingNodeForPacket(const QByteArray& packet); + SharedNodePointer addOrUpdateNode(const QUuid& uuid, char nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket); void processNodeData(const HifiSockAddr& senderSockAddr, const QByteArray& packet); @@ -119,7 +120,7 @@ public: void loadData(QSettings* settings); void saveData(QSettings* settings); - const HifiSockAddr* getNodeActiveSocketOrPing(Node* node); + const HifiSockAddr* getNodeActiveSocketOrPing(const SharedNodePointer& node); public slots: void sendDomainServerCheckIn(); void pingInactiveNodes(); From fa1825fa32f3e9b57f8f93b9de476bc48f7e4e12 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 7 Feb 2014 10:20:50 -0800 Subject: [PATCH 23/42] repairs to ping-reply, removal of deconstructPacketHeader to simply return UUID --- animation-server/src/AnimationServer.cpp | 4 +- assignment-client/src/audio/AudioMixer.cpp | 4 +- assignment-client/src/avatars/AvatarMixer.cpp | 10 +-- assignment-client/src/octree/OctreeServer.cpp | 7 +- domain-server/src/DomainServer.cpp | 4 +- interface/src/DatagramProcessor.cpp | 7 +- libraries/shared/src/NodeList.cpp | 74 ++++++++++--------- libraries/shared/src/NodeList.h | 13 +++- libraries/shared/src/PacketHeaders.cpp | 9 +-- libraries/shared/src/PacketHeaders.h | 2 +- 10 files changed, 65 insertions(+), 69 deletions(-) diff --git a/animation-server/src/AnimationServer.cpp b/animation-server/src/AnimationServer.cpp index 466ed7cf93..78966da2b5 100644 --- a/animation-server/src/AnimationServer.cpp +++ b/animation-server/src/AnimationServer.cpp @@ -835,10 +835,8 @@ void AnimationServer::readPendingDatagrams() { int headerBytes = numBytesForPacketHeader(receivedPacket); // PacketType_JURISDICTION, first byte is the node type... if (receivedPacket.data()[headerBytes] == NodeType::VoxelServer && ::jurisdictionListener) { - QUuid nodeUUID; - deconstructPacketHeader(receivedPacket, nodeUUID); - SharedNodePointer matchedNode = NodeList::getInstance()->nodeWithUUID(nodeUUID); + SharedNodePointer matchedNode = NodeList::getInstance()->sendingNodeForPacket(receivedPacket); if (matchedNode) { ::jurisdictionListener->queueReceivedPacket(matchedNode, receivedPacket); } diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index e9c0aafabb..3a736fd51c 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -213,12 +213,10 @@ void AudioMixer::processDatagram(const QByteArray& dataByteArray, const HifiSock if (mixerPacketType == PacketTypeMicrophoneAudioNoEcho || mixerPacketType == PacketTypeMicrophoneAudioWithEcho || mixerPacketType == PacketTypeInjectAudio) { - QUuid nodeUUID; - deconstructPacketHeader(dataByteArray, nodeUUID); NodeList* nodeList = NodeList::getInstance(); - SharedNodePointer matchingNode = nodeList->nodeWithUUID(nodeUUID); + SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(dataByteArray); if (matchingNode) { nodeList->updateNodeWithData(matchingNode.data(), senderSockAddr, dataByteArray); diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 5b085fbcd2..9971bb51af 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -142,11 +142,9 @@ void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSoc switch (packetTypeForPacket(dataByteArray)) { case PacketTypeAvatarData: { - QUuid nodeUUID; - deconstructPacketHeader(dataByteArray, nodeUUID); // add or update the node in our list - SharedNodePointer avatarNode = nodeList->nodeWithUUID(nodeUUID); + SharedNodePointer avatarNode = nodeList->sendingNodeForPacket(dataByteArray); if (avatarNode) { // parse positional data from an node @@ -156,11 +154,9 @@ void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSoc break; } case PacketTypeAvatarIdentity: { - QUuid nodeUUID; - deconstructPacketHeader(dataByteArray, nodeUUID); // check if we have a matching node in our list - SharedNodePointer avatarNode = nodeList->nodeWithUUID(nodeUUID); + SharedNodePointer avatarNode = nodeList->sendingNodeForPacket(dataByteArray); if (avatarNode && avatarNode->getLinkedData()) { AvatarMixerClientData* nodeData = reinterpret_cast(avatarNode->getLinkedData()); @@ -170,7 +166,7 @@ void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSoc QByteArray identityPacket = byteArrayWithPopluatedHeader(PacketTypeAvatarIdentity); QByteArray individualByteArray = nodeData->identityByteArray(); - individualByteArray.replace(0, NUM_BYTES_RFC4122_UUID, nodeUUID.toRfc4122()); + individualByteArray.replace(0, NUM_BYTES_RFC4122_UUID, avatarNode->getUUID().toRfc4122()); identityPacket.append(individualByteArray); diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 10dc22fa96..4eff13f658 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -463,10 +463,7 @@ void OctreeServer::processDatagram(const QByteArray& dataByteArray, const HifiSo PacketType packetType = packetTypeForPacket(dataByteArray); - QUuid nodeUUID; - deconstructPacketHeader(dataByteArray, nodeUUID); - - SharedNodePointer matchingNode = nodeList->nodeWithUUID(nodeUUID); + SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(dataByteArray); if (packetType == getMyQueryMessageType()) { bool debug = false; @@ -487,7 +484,7 @@ void OctreeServer::processDatagram(const QByteArray& dataByteArray, const HifiSo } OctreeQueryNode* nodeData = (OctreeQueryNode*) matchingNode->getLinkedData(); if (nodeData && !nodeData->isOctreeSendThreadInitalized()) { - nodeData->initializeOctreeSendThread(this, nodeUUID); + nodeData->initializeOctreeSendThread(this, matchingNode->getUUID()); } } } else if (packetType == PacketTypeJurisdictionRequest) { diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index e847143eaf..6ce71cae01 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -229,7 +229,7 @@ void DomainServer::readAvailableDatagrams() { QByteArray receivedPacket; NodeType_t nodeType; - QUuid nodeUUID; + while (nodeList->getNodeSocket().hasPendingDatagrams()) { receivedPacket.resize(nodeList->getNodeSocket().pendingDatagramSize()); @@ -244,7 +244,7 @@ void DomainServer::readAvailableDatagrams() { QDataStream packetStream(receivedPacket); packetStream.skipRawData(numBytesForPacketHeader(receivedPacket)); - deconstructPacketHeader(receivedPacket, nodeUUID); + QUuid nodeUUID = uuidFromPacketHeader(receivedPacket); packetStream >> nodeType; packetStream >> nodePublicAddress >> nodeLocalAddress; diff --git a/interface/src/DatagramProcessor.cpp b/interface/src/DatagramProcessor.cpp index e3f46c52d4..36f03c39f0 100644 --- a/interface/src/DatagramProcessor.cpp +++ b/interface/src/DatagramProcessor.cpp @@ -40,9 +40,6 @@ void DatagramProcessor::processDatagrams() { _packetCount++; _byteCount += incomingPacket.size(); - QUuid nodeUUID; - deconstructPacketHeader(incomingPacket, nodeUUID); - if (packetVersionMatch(incomingPacket)) { // only process this packet if we have a match on the packet version switch (packetTypeForPacket(incomingPacket)) { @@ -87,7 +84,7 @@ void DatagramProcessor::processDatagrams() { printf("got PacketType_VOXEL_DATA, sequence:%d flightTime:%d\n", sequence, flightTime); } - SharedNodePointer matchedNode = NodeList::getInstance()->nodeWithUUID(nodeUUID); + SharedNodePointer matchedNode = NodeList::getInstance()->sendingNodeForPacket(incomingPacket); if (matchedNode) { // add this packet to our list of voxel packets and process them on the voxel processing @@ -103,7 +100,7 @@ void DatagramProcessor::processDatagrams() { case PacketTypeKillAvatar: case PacketTypeAvatarIdentity: { // update having heard from the avatar-mixer and record the bytes received - SharedNodePointer avatarMixer = nodeList->nodeWithUUID(nodeUUID); + SharedNodePointer avatarMixer = nodeList->sendingNodeForPacket(incomingPacket); if (avatarMixer) { avatarMixer->setLastHeardMicrostamp(usecTimestampNow()); diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 6b9ef4f406..ed3e37dae6 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -142,13 +142,9 @@ void NodeList::setDomainHostname(const QString& domainHostname) { } } -void NodeList::timePingReply(const QByteArray& packet) { - QUuid nodeUUID; - deconstructPacketHeader(packet, nodeUUID); +void NodeList::timePingReply(const QByteArray& packet, const SharedNodePointer& sendingNode) { - SharedNodePointer matchingNode = nodeWithUUID(nodeUUID); - - if (matchingNode) { + if (sendingNode) { QDataStream packetStream(packet); packetStream.skipRawData(numBytesForPacketHeader(packet)); @@ -165,13 +161,13 @@ void NodeList::timePingReply(const QByteArray& packet) { quint64 othersExprectedReply = ourOriginalTime + oneWayFlightTime; int clockSkew = othersReplyTime - othersExprectedReply; - matchingNode->setPingMs(pingTime / 1000); - matchingNode->setClockSkewUsec(clockSkew); + sendingNode->setPingMs(pingTime / 1000); + sendingNode->setClockSkewUsec(clockSkew); const bool wantDebug = false; if (wantDebug) { - qDebug() << "PING_REPLY from node " << *matchingNode << "\n" << + qDebug() << "PING_REPLY from node " << *sendingNode << "\n" << " now: " << now << "\n" << " ourTime: " << ourOriginalTime << "\n" << " pingTime: " << pingTime << "\n" << @@ -200,11 +196,16 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr break; } case PacketTypePingReply: { - // activate the appropriate socket for this node, if not yet updated - activateSocketFromNodeCommunication(senderSockAddr); - - // set the ping time for this node for stat collection - timePingReply(packet); + SharedNodePointer sendingNode = sendingNodeForPacket(packet); + + if (sendingNode) { + // activate the appropriate socket for this node, if not yet updated + activateSocketFromNodeCommunication(packet, sendingNode); + + // set the ping time for this node for stat collection + timePingReply(packet, sendingNode); + } + break; } case PacketTypeStunResponse: { @@ -252,8 +253,7 @@ SharedNodePointer NodeList::nodeWithUUID(const QUuid& nodeUUID) { } SharedNodePointer NodeList::sendingNodeForPacket(const QByteArray& packet) { - QUuid nodeUUID; - deconstructPacketHeader(packet, nodeUUID); + QUuid nodeUUID = uuidFromPacketHeader(packet); // return the matching node, or NULL if there is no match return nodeWithUUID(nodeUUID); @@ -590,10 +590,12 @@ void NodeList::sendAssignment(Assignment& assignment) { _nodeSocket.writeDatagram(packet, assignmentServerSocket->getAddress(), assignmentServerSocket->getPort()); } -QByteArray NodeList::constructPingPacket() { +QByteArray NodeList::constructPingPacket(PingType_t pingType) { QByteArray pingPacket = byteArrayWithPopluatedHeader(PacketTypePing); QDataStream packetStream(&pingPacket, QIODevice::Append); + + packetStream << pingType; packetStream << usecTimestampNow(); return pingPacket; @@ -615,11 +617,13 @@ QByteArray NodeList::constructPingReplyPacket(const QByteArray& pingPacket) { } void NodeList::pingPublicAndLocalSocketsForInactiveNode(const SharedNodePointer& node) { - QByteArray pingPacket = constructPingPacket(); - + // send the ping packet to the local and public sockets for this node - writeDatagram(pingPacket, node); - writeDatagram(pingPacket, node); + QByteArray localPingPacket = constructPingPacket(PingType::Local); + writeDatagram(localPingPacket, node, node->getLocalSocket()); + + QByteArray publicPingPacket = constructPingPacket(PingType::Public); + writeDatagram(publicPingPacket, node, node->getPublicSocket()); } SharedNodePointer NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, @@ -703,20 +707,20 @@ const HifiSockAddr* NodeList::getNodeActiveSocketOrPing(const SharedNodePointer& return NULL; } -void NodeList::activateSocketFromNodeCommunication(const HifiSockAddr& nodeAddress) { - - foreach (const SharedNodePointer& node, _nodeHash) { - if (!node->getActiveSocket()) { - // check both the public and local addresses for each node to see if we find a match - // prioritize the private address so that we prune erroneous local matches - if (node->getPublicSocket() == nodeAddress) { - node->activatePublicSocket(); - break; - } else if (node->getLocalSocket() == nodeAddress) { - node->activateLocalSocket(); - break; - } - } +void NodeList::activateSocketFromNodeCommunication(const QByteArray& packet, const SharedNodePointer& sendingNode) { + // deconstruct this ping packet to see if it is a public or local reply + QDataStream packetStream(packet); + packetStream.skipRawData(numBytesForPacketHeader(packet)); + + quint8 pingType; + packetStream >> pingType; + + // if this is a local or public ping then we can activate a socket + // we do nothing with agnostic pings, those are simply for timing + if (pingType == PingType::Local) { + sendingNode->activateLocalSocket(); + } else if (pingType == PingType::Public) { + sendingNode->activatePublicSocket(); } } diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 1a035e91d1..3a71ee7620 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -54,6 +54,13 @@ typedef QSharedPointer SharedNodePointer; typedef QHash NodeHash; Q_DECLARE_METATYPE(SharedNodePointer) +typedef quint8 PingType_t; +namespace PingType { + const PingType_t Agnostic = 0; + const PingType_t Local = 1; + const PingType_t Public = 2; +} + class NodeList : public QObject { Q_OBJECT public: @@ -100,7 +107,7 @@ public: void setAssignmentServerSocket(const HifiSockAddr& serverSocket) { _assignmentServerSocket = serverSocket; } void sendAssignment(Assignment& assignment); - QByteArray constructPingPacket(); + QByteArray constructPingPacket(PingType_t pingType = PingType::Agnostic); QByteArray constructPingReplyPacket(const QByteArray& pingPacket); void pingPublicAndLocalSocketsForInactiveNode(const SharedNodePointer& node); @@ -158,8 +165,8 @@ private: bool _hasCompletedInitialSTUNFailure; unsigned int _stunRequestsSinceSuccess; - void activateSocketFromNodeCommunication(const HifiSockAddr& nodeSockAddr); - void timePingReply(const QByteArray& packet); + void activateSocketFromNodeCommunication(const QByteArray& packet, const SharedNodePointer& sendingNode); + void timePingReply(const QByteArray& packet, const SharedNodePointer& sendingNode); void resetDomainData(char domainField[], const char* domainData); void domainLookup(); void clear(); diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index 99066cb66b..16e1b3ce78 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -95,8 +95,7 @@ bool packetVersionMatch(const QByteArray& packet) { PacketType mismatchType = packetTypeForPacket(packet); int numPacketTypeBytes = arithmeticCodingValueFromBuffer(packet.data()); - QUuid nodeUUID; - deconstructPacketHeader(packet, nodeUUID); + QUuid nodeUUID = uuidFromPacketHeader(packet); qDebug() << "Packet mismatch on" << packetTypeForPacket(packet) << "- Sender" << nodeUUID << "sent" << qPrintable(QString::number(packet[numPacketTypeBytes])) << "but" @@ -120,9 +119,9 @@ int numBytesForPacketHeaderGivenPacketType(PacketType type) { return (int) ceilf((float)type / 255) + NUM_STATIC_HEADER_BYTES; } -void deconstructPacketHeader(const QByteArray& packet, QUuid& senderUUID) { - senderUUID = QUuid::fromRfc4122(packet.mid(numBytesArithmeticCodingFromBuffer(packet.data()) + sizeof(PacketVersion), - NUM_BYTES_RFC4122_UUID)); +QUuid uuidFromPacketHeader(const QByteArray& packet) { + return QUuid::fromRfc4122(packet.mid(numBytesArithmeticCodingFromBuffer(packet.data()) + sizeof(PacketVersion), + NUM_BYTES_RFC4122_UUID)); } PacketType packetTypeForPacket(const QByteArray& packet) { diff --git a/libraries/shared/src/PacketHeaders.h b/libraries/shared/src/PacketHeaders.h index 691dee861b..ad669daece 100644 --- a/libraries/shared/src/PacketHeaders.h +++ b/libraries/shared/src/PacketHeaders.h @@ -76,7 +76,7 @@ int numBytesForPacketHeader(const QByteArray& packet); int numBytesForPacketHeader(const char* packet); int numBytesForPacketHeaderGivenPacketType(PacketType type); -void deconstructPacketHeader(const QByteArray& packet, QUuid& senderUUID); +QUuid uuidFromPacketHeader(const QByteArray& packet); PacketType packetTypeForPacket(const QByteArray& packet); PacketType packetTypeForPacket(const char* packet); From 7ceacd27517dd3856584d5a20ad73be1a43a8900 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 7 Feb 2014 10:24:01 -0800 Subject: [PATCH 24/42] remove blank if and fix ping reply construction --- libraries/audio/src/AudioInjector.cpp | 4 ---- libraries/shared/src/NodeList.cpp | 5 ++++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 905c1ecfc6..ff243459b7 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -96,10 +96,6 @@ void AudioInjector::injectAudio() { // send off this audio packet nodeList->writeDatagram(injectAudioPacket, audioMixer); - if (audioMixer && nodeList->getNodeActiveSocketOrPing(audioMixer)) { - - } - currentSendPosition += bytesToCopy; // send two packets before the first sleep so the mixer can start playback right away diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index ed3e37dae6..c30c6de56a 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -605,13 +605,16 @@ QByteArray NodeList::constructPingReplyPacket(const QByteArray& pingPacket) { QDataStream pingPacketStream(pingPacket); pingPacketStream.skipRawData(numBytesForPacketHeader(pingPacket)); + PingType_t typeFromOriginalPing; + pingPacketStream >> typeFromOriginalPing; + quint64 timeFromOriginalPing; pingPacketStream >> timeFromOriginalPing; QByteArray replyPacket = byteArrayWithPopluatedHeader(PacketTypePingReply); QDataStream packetStream(&replyPacket, QIODevice::Append); - packetStream << timeFromOriginalPing << usecTimestampNow(); + packetStream << typeFromOriginalPing << timeFromOriginalPing << usecTimestampNow(); return replyPacket; } From d39cccde774c0b26f801533fb451de16953b4134 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 7 Feb 2014 10:32:16 -0800 Subject: [PATCH 25/42] add a method to find a node and upate based on packet --- assignment-client/src/audio/AudioMixer.cpp | 16 +------ assignment-client/src/avatars/AvatarMixer.cpp | 10 +---- assignment-client/src/octree/OctreeServer.cpp | 10 +---- libraries/shared/src/NodeList.cpp | 42 +++++++++---------- libraries/shared/src/NodeList.h | 3 +- 5 files changed, 26 insertions(+), 55 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 3a736fd51c..6dbfb58f9a 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -213,20 +213,8 @@ void AudioMixer::processDatagram(const QByteArray& dataByteArray, const HifiSock if (mixerPacketType == PacketTypeMicrophoneAudioNoEcho || mixerPacketType == PacketTypeMicrophoneAudioWithEcho || mixerPacketType == PacketTypeInjectAudio) { - - NodeList* nodeList = NodeList::getInstance(); - - SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(dataByteArray); - - if (matchingNode) { - nodeList->updateNodeWithData(matchingNode.data(), senderSockAddr, dataByteArray); - - if (!matchingNode->getActiveSocket()) { - // we don't have an active socket for this node, but they're talking to us - // this means they've heard from us and can reply, let's assume public is active - matchingNode->activatePublicSocket(); - } - } + + NodeList::getInstance()->findNodeAndUpdateWithDataFromPacket(dataByteArray); } else { // let processNodeData handle it. NodeList::getInstance()->processNodeData(senderSockAddr, dataByteArray); diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 9971bb51af..5e0da14a59 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -142,15 +142,7 @@ void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSoc switch (packetTypeForPacket(dataByteArray)) { case PacketTypeAvatarData: { - - // add or update the node in our list - SharedNodePointer avatarNode = nodeList->sendingNodeForPacket(dataByteArray); - - if (avatarNode) { - // parse positional data from an node - nodeList->updateNodeWithData(avatarNode.data(), senderSockAddr, dataByteArray); - - } + nodeList->findNodeAndUpdateWithDataFromPacket(dataByteArray); break; } case PacketTypeAvatarIdentity: { diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 4eff13f658..48fd0b0a8d 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -473,15 +473,9 @@ void OctreeServer::processDatagram(const QByteArray& dataByteArray, const HifiSo // If we got a PacketType_VOXEL_QUERY, then we're talking to an NodeType_t_AVATAR, and we // need to make sure we have it in our nodeList. - - if (matchingNode) { - nodeList->updateNodeWithData(matchingNode.data(), senderSockAddr, dataByteArray); - if (!matchingNode->getActiveSocket()) { - // we don't have an active socket for this node, but they're talking to us - // this means they've heard from us and can reply, let's assume public is active - matchingNode->activatePublicSocket(); - } + nodeList->updateNodeWithDataFromPacket(matchingNode, dataByteArray); + OctreeQueryNode* nodeData = (OctreeQueryNode*) matchingNode->getLinkedData(); if (nodeData && !nodeData->isOctreeSendThreadInitalized()) { nodeData->initializeOctreeSendThread(this, matchingNode->getUUID()); diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index c30c6de56a..46234c510f 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -219,32 +219,28 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr } } -int NodeList::updateNodeWithData(Node *node, const HifiSockAddr& senderSockAddr, const QByteArray& packet) { - QMutexLocker locker(&node->getMutex()); - - node->setLastHeardMicrostamp(usecTimestampNow()); - - if (!senderSockAddr.isNull() && !node->getActiveSocket()) { - if (senderSockAddr == node->getPublicSocket()) { - node->activatePublicSocket(); - } else if (senderSockAddr == node->getLocalSocket()) { - node->activateLocalSocket(); - } +int NodeList::updateNodeWithDataFromPacket(const SharedNodePointer& matchingNode, const QByteArray &packet) { + QMutexLocker locker(&matchingNode->getMutex()); + + matchingNode->setLastHeardMicrostamp(usecTimestampNow()); + matchingNode->recordBytesReceived(packet.size()); + + if (!matchingNode->getLinkedData() && linkedDataCreateCallback) { + linkedDataCreateCallback(matchingNode.data()); } + + return matchingNode->getLinkedData()->parseData(packet); +} - if (node->getActiveSocket() || senderSockAddr.isNull()) { - node->recordBytesReceived(packet.size()); - - if (!node->getLinkedData() && linkedDataCreateCallback) { - linkedDataCreateCallback(node); - } - - int numParsedBytes = node->getLinkedData()->parseData(packet); - return numParsedBytes; - } else { - // we weren't able to match the sender address to the address we have for this node, unlock and don't parse - return 0; +int NodeList::findNodeAndUpdateWithDataFromPacket(const QByteArray& packet) { + SharedNodePointer matchingNode = sendingNodeForPacket(packet); + + if (matchingNode) { + updateNodeWithDataFromPacket(matchingNode, packet); } + + // we weren't able to match the sender address to the address we have for this node, unlock and don't parse + return 0; } SharedNodePointer NodeList::nodeWithUUID(const QUuid& nodeUUID) { diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 3a71ee7620..2e89395d3e 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -119,7 +119,8 @@ public: void processNodeData(const HifiSockAddr& senderSockAddr, const QByteArray& packet); void processKillNode(const QByteArray& datagram); - int updateNodeWithData(Node *node, const HifiSockAddr& senderSockAddr, const QByteArray& packet); + int updateNodeWithDataFromPacket(const SharedNodePointer& matchingNode, const QByteArray& packet); + int findNodeAndUpdateWithDataFromPacket(const QByteArray& packet); unsigned broadcastToNodes(const QByteArray& packet, const NodeSet& destinationNodeTypes); SharedNodePointer soloNodeOfType(char nodeType); From 997bea708df5b0c47a94b8134c13617bfe7639fa Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 7 Feb 2014 10:32:48 -0800 Subject: [PATCH 26/42] fix a PacketTypeVoxelQuery typo --- assignment-client/src/octree/OctreeServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 48fd0b0a8d..1b66c9ddba 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -468,7 +468,7 @@ void OctreeServer::processDatagram(const QByteArray& dataByteArray, const HifiSo if (packetType == getMyQueryMessageType()) { bool debug = false; if (debug) { - qDebug() << "Got PacketType_VOXEL_QUERY at" << usecTimestampNow(); + qDebug() << "Got PacketTypeVoxelQuery at" << usecTimestampNow(); } // If we got a PacketType_VOXEL_QUERY, then we're talking to an NodeType_t_AVATAR, and we From 66d4eeb8059755b9a7f1615f8f2194b57b0e2fae Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 7 Feb 2014 11:10:38 -0800 Subject: [PATCH 27/42] enforce both a version and hash match for packets --- animation-server/src/AnimationServer.cpp | 2 +- assignment-client/src/AssignmentClient.cpp | 2 +- data-server/src/DataServer.cpp | 2 +- domain-server/src/DomainServer.cpp | 2 +- interface/src/DatagramProcessor.cpp | 2 +- interface/src/VoxelPacketProcessor.cpp | 2 +- libraries/shared/src/NodeList.cpp | 81 ++++++++++++++++------ libraries/shared/src/NodeList.h | 2 + libraries/shared/src/PacketHeaders.cpp | 34 ++++----- libraries/shared/src/PacketHeaders.h | 7 +- 10 files changed, 86 insertions(+), 50 deletions(-) diff --git a/animation-server/src/AnimationServer.cpp b/animation-server/src/AnimationServer.cpp index 78966da2b5..3151445794 100644 --- a/animation-server/src/AnimationServer.cpp +++ b/animation-server/src/AnimationServer.cpp @@ -830,7 +830,7 @@ void AnimationServer::readPendingDatagrams() { receivedPacket.resize(nodeList->getNodeSocket().pendingDatagramSize()); nodeList->getNodeSocket().readDatagram(receivedPacket.data(), receivedPacket.size(), nodeSockAddr.getAddressPointer(), nodeSockAddr.getPortPointer()); - if (packetVersionMatch(receivedPacket)) { + if (nodeList->packetVersionAndHashMatch(receivedPacket)) { if (packetTypeForPacket(receivedPacket) == PacketTypeJurisdiction) { int headerBytes = numBytesForPacketHeader(receivedPacket); // PacketType_JURISDICTION, first byte is the node type... diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index b294f48fac..8add7d90f8 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -111,7 +111,7 @@ void AssignmentClient::readPendingDatagrams() { nodeList->getNodeSocket().readDatagram(receivedPacket.data(), receivedPacket.size(), senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer()); - if (packetVersionMatch(receivedPacket)) { + if (nodeList->packetVersionAndHashMatch(receivedPacket)) { if (_currentAssignment) { // have the threaded current assignment handle this datagram QMetaObject::invokeMethod(_currentAssignment, "processDatagram", Qt::QueuedConnection, diff --git a/data-server/src/DataServer.cpp b/data-server/src/DataServer.cpp index 43fc52fb06..97228b67a3 100644 --- a/data-server/src/DataServer.cpp +++ b/data-server/src/DataServer.cpp @@ -66,7 +66,7 @@ void DataServer::readPendingDatagrams() { PacketType requestType = packetTypeForPacket(receivedPacket); if ((requestType == PacketTypeDataServerPut || requestType == PacketTypeDataServerGet) && - packetVersionMatch(receivedPacket)) { + receivedPacket[numBytesArithmeticCodingFromBuffer(receivedPacket.data())] == versionForPacketType(requestType)) { QDataStream packetStream(receivedPacket); int numReceivedHeaderBytes = numBytesForPacketHeader(receivedPacket); diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 6ce71cae01..2a98c9b8b0 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -236,7 +236,7 @@ void DomainServer::readAvailableDatagrams() { nodeList->getNodeSocket().readDatagram(receivedPacket.data(), receivedPacket.size(), senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer()); - if (packetVersionMatch(receivedPacket)) { + if (nodeList->packetVersionAndHashMatch(receivedPacket)) { PacketType requestType = packetTypeForPacket(receivedPacket); if (requestType == PacketTypeDomainListRequest) { diff --git a/interface/src/DatagramProcessor.cpp b/interface/src/DatagramProcessor.cpp index 36f03c39f0..6271ef5fde 100644 --- a/interface/src/DatagramProcessor.cpp +++ b/interface/src/DatagramProcessor.cpp @@ -40,7 +40,7 @@ void DatagramProcessor::processDatagrams() { _packetCount++; _byteCount += incomingPacket.size(); - if (packetVersionMatch(incomingPacket)) { + if (nodeList->packetVersionAndHashMatch(incomingPacket)) { // only process this packet if we have a match on the packet version switch (packetTypeForPacket(incomingPacket)) { case PacketTypeTransmitterData: diff --git a/interface/src/VoxelPacketProcessor.cpp b/interface/src/VoxelPacketProcessor.cpp index b5ec4247f2..dce391e587 100644 --- a/interface/src/VoxelPacketProcessor.cpp +++ b/interface/src/VoxelPacketProcessor.cpp @@ -48,7 +48,7 @@ void VoxelPacketProcessor::processPacket(const SharedNodePointer& sendingNode, c wasStatsPacket = true; if (messageLength > statsMessageLength) { mutablePacket = mutablePacket.mid(statsMessageLength); - if (!packetVersionMatch(packet)) { + if (!NodeList::getInstance()->packetVersionAndHashMatch(packet)) { return; // bail since piggyback data doesn't match our versioning } } else { diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 46234c510f..ba890564ce 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -80,30 +80,64 @@ NodeList::~NodeList() { clear(); } -qint64 NodeList::writeDatagram(const QByteArray& datagram, const SharedNodePointer& destinationNode, - const HifiSockAddr& overridenSockAddr) { +bool NodeList::packetVersionAndHashMatch(const QByteArray& packet) { + // currently this just checks if the version in the packet matches our return from versionForPacketType + // may need to be expanded in the future for types and versions that take > than 1 byte - // setup the MD5 hash for source verification in the header - int numBytesPacketHeader = numBytesForPacketHeader(datagram); - QByteArray dataSecretHash = QCryptographicHash::hash(datagram.mid(numBytesPacketHeader) - + destinationNode->getConnectionSecret().toRfc4122(), - QCryptographicHash::Md5); - QByteArray datagramWithHash = datagram; - datagramWithHash.replace(numBytesPacketHeader - NUM_BYTES_MD5_HASH, NUM_BYTES_MD5_HASH, dataSecretHash); + if (packet[1] != versionForPacketType(packetTypeForPacket(packet)) + && packetTypeForPacket(packet) != PacketTypeStunResponse) { + PacketType mismatchType = packetTypeForPacket(packet); + int numPacketTypeBytes = arithmeticCodingValueFromBuffer(packet.data()); + + qDebug() << "Packet version mismatch on" << packetTypeForPacket(packet) << "- Sender" + << uuidFromPacketHeader(packet) << "sent" << qPrintable(QString::number(packet[numPacketTypeBytes])) << "but" + << qPrintable(QString::number(versionForPacketType(mismatchType))) << "expected."; + } - // if we don't have an ovveriden address, assume they want to send to the node's active socket - const HifiSockAddr* destinationSockAddr = &overridenSockAddr; - if (overridenSockAddr.isNull()) { - if (getNodeActiveSocketOrPing(destinationNode)) { - // use the node's active socket as the destination socket - destinationSockAddr = destinationNode->getActiveSocket(); + if (packetTypeForPacket(packet) != PacketTypeDomainList && packetTypeForPacket(packet) != PacketTypeDomainListRequest) { + // figure out which node this is from + SharedNodePointer sendingNode = sendingNodeForPacket(packet); + if (sendingNode) { + // check if the md5 hash in the header matches the hash we would expect + if (hashFromPacketHeader(packet) == hashForPacketAndConnectionUUID(packet, sendingNode->getConnectionSecret())) { + return true; + } else { + qDebug() << "Packet hash mismatch" << packetTypeForPacket(packet) << "received from known node with UUID" + << uuidFromPacketHeader(packet); + } } else { - // we don't have a socket to send to, return 0 - return 0; + qDebug() << "Packet of type" << packetTypeForPacket(packet) << "received from unknown node with UUID" + << uuidFromPacketHeader(packet); } } - return _nodeSocket.writeDatagram(datagramWithHash, destinationSockAddr->getAddress(), destinationSockAddr->getPort()); + return false; +} + +qint64 NodeList::writeDatagram(const QByteArray& datagram, const SharedNodePointer& destinationNode, + const HifiSockAddr& overridenSockAddr) { + if (destinationNode) { + // if we don't have an ovveriden address, assume they want to send to the node's active socket + const HifiSockAddr* destinationSockAddr = &overridenSockAddr; + if (overridenSockAddr.isNull()) { + if (getNodeActiveSocketOrPing(destinationNode)) { + // use the node's active socket as the destination socket + destinationSockAddr = destinationNode->getActiveSocket(); + } else { + // we don't have a socket to send to, return 0 + return 0; + } + } + + QByteArray datagramCopy = datagram; + // setup the MD5 hash for source verification in the header + replaceHashInPacketGivenConnectionUUID(datagramCopy, destinationNode->getConnectionSecret()); + + return _nodeSocket.writeDatagram(datagramCopy, destinationSockAddr->getAddress(), destinationSockAddr->getPort()); + } + + // didn't have a destinationNode to send to, return 0 + return 0; } qint64 NodeList::writeDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode, @@ -191,8 +225,11 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr } case PacketTypePing: { // send back a reply - QByteArray replyPacket = constructPingReplyPacket(packet); - writeDatagram(replyPacket, sendingNodeForPacket(packet), senderSockAddr); + if (sendingNodeForPacket(packet)) { + QByteArray replyPacket = constructPingReplyPacket(packet); + writeDatagram(replyPacket, sendingNodeForPacket(packet), senderSockAddr); + } + break; } case PacketTypePingReply: { @@ -716,9 +753,9 @@ void NodeList::activateSocketFromNodeCommunication(const QByteArray& packet, con // if this is a local or public ping then we can activate a socket // we do nothing with agnostic pings, those are simply for timing - if (pingType == PingType::Local) { + if (pingType == PingType::Local && sendingNode->getActiveSocket() != &sendingNode->getLocalSocket()) { sendingNode->activateLocalSocket(); - } else if (pingType == PingType::Public) { + } else if (pingType == PingType::Public && !sendingNode->getActiveSocket()) { sendingNode->activatePublicSocket(); } } diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 2e89395d3e..408459e51f 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -84,6 +84,8 @@ public: QUdpSocket& getNodeSocket() { return _nodeSocket; } + bool packetVersionAndHashMatch(const QByteArray& packet); + qint64 writeDatagram(const QByteArray& datagram, const SharedNodePointer& destinationNode, const HifiSockAddr& overridenSockAddr = HifiSockAddr()); qint64 writeDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode, diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index 16e1b3ce78..7193b6f648 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -85,26 +85,6 @@ int populatePacketHeader(char* packet, PacketType type, const QUuid& connectionU return position - packet; } -bool packetVersionMatch(const QByteArray& packet) { - // currently this just checks if the version in the packet matches our return from versionForPacketType - // may need to be expanded in the future for types and versions that take > than 1 byte - - if (packet[1] == versionForPacketType(packetTypeForPacket(packet)) || packetTypeForPacket(packet) == PacketTypeStunResponse) { - return true; - } else { - PacketType mismatchType = packetTypeForPacket(packet); - int numPacketTypeBytes = arithmeticCodingValueFromBuffer(packet.data()); - - QUuid nodeUUID = uuidFromPacketHeader(packet); - - qDebug() << "Packet mismatch on" << packetTypeForPacket(packet) << "- Sender" - << nodeUUID << "sent" << qPrintable(QString::number(packet[numPacketTypeBytes])) << "but" - << qPrintable(QString::number(versionForPacketType(mismatchType))) << "expected."; - - return false; - } -} - int numBytesForPacketHeader(const QByteArray& packet) { // returns the number of bytes used for the type, version, and UUID return numBytesArithmeticCodingFromBuffer(packet.data()) + NUM_STATIC_HEADER_BYTES; @@ -124,6 +104,20 @@ QUuid uuidFromPacketHeader(const QByteArray& packet) { NUM_BYTES_RFC4122_UUID)); } +QByteArray hashFromPacketHeader(const QByteArray& packet) { + return packet.mid(NUM_STATIC_HEADER_BYTES - NUM_BYTES_MD5_HASH, NUM_BYTES_MD5_HASH); +} + +QByteArray hashForPacketAndConnectionUUID(const QByteArray& packet, const QUuid& connectionUUID) { + return QCryptographicHash::hash(packet.mid(numBytesForPacketHeader(packet)) + + connectionUUID.toRfc4122(), QCryptographicHash::Md5); +} + +void replaceHashInPacketGivenConnectionUUID(QByteArray& packet, const QUuid& connectionUUID) { + packet.replace(numBytesForPacketHeader(packet) - NUM_BYTES_MD5_HASH, NUM_BYTES_MD5_HASH, + hashForPacketAndConnectionUUID(packet, connectionUUID)); +} + PacketType packetTypeForPacket(const QByteArray& packet) { return (PacketType) arithmeticCodingValueFromBuffer(packet.data()); } diff --git a/libraries/shared/src/PacketHeaders.h b/libraries/shared/src/PacketHeaders.h index ad669daece..c1a5a34114 100644 --- a/libraries/shared/src/PacketHeaders.h +++ b/libraries/shared/src/PacketHeaders.h @@ -70,17 +70,20 @@ QByteArray byteArrayWithPopluatedHeader(PacketType type, const QUuid& connection int populatePacketHeader(QByteArray& packet, PacketType type, const QUuid& connectionUUID = nullUUID); int populatePacketHeader(char* packet, PacketType type, const QUuid& connectionUUID = nullUUID); -bool packetVersionMatch(const QByteArray& packet); - int numBytesForPacketHeader(const QByteArray& packet); int numBytesForPacketHeader(const char* packet); int numBytesForPacketHeaderGivenPacketType(PacketType type); QUuid uuidFromPacketHeader(const QByteArray& packet); +QByteArray hashFromPacketHeader(const QByteArray& packet); +QByteArray hashForPacketAndConnectionUUID(const QByteArray& packet, const QUuid& connectionUUID); +void replaceHashInPacketGivenConnectionUUID(QByteArray& packet, const QUuid& connectionUUID); + PacketType packetTypeForPacket(const QByteArray& packet); PacketType packetTypeForPacket(const char* packet); int arithmeticCodingValueFromBuffer(const char* checkValue); +int numBytesArithmeticCodingFromBuffer(const char* checkValue); #endif From 67bef20f93d48192bcc21c58e3858a16e5cb6cf6 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 7 Feb 2014 11:26:15 -0800 Subject: [PATCH 28/42] Have eyes converge on hovered avatar/voxel. Closes #1883. --- interface/src/Application.cpp | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 84ece357a7..5fd51681b4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1963,8 +1963,13 @@ void Application::updateMouseRay() { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateMouseRay()"); - _viewFrustum.computePickRay(_mouseX / (float)_glWidget->width(), _mouseY / (float)_glWidget->height(), - _mouseRayOrigin, _mouseRayDirection); + // if the mouse pointer isn't visible, act like it's at the center of the screen + float x = 0.5f, y = 0.5f; + if (!_mouseHidden) { + x = _mouseX / (float)_glWidget->width(); + y = _mouseY / (float)_glWidget->height(); + } + _viewFrustum.computePickRay(x, y, _mouseRayOrigin, _mouseRayDirection); // adjust for mirroring if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { @@ -2001,18 +2006,20 @@ void Application::updateMyAvatarLookAtPosition(glm::vec3& lookAtSpot) { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateMyAvatarLookAtPosition()"); - const float FAR_AWAY_STARE = TREE_SCALE; if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { lookAtSpot = _myCamera.getPosition(); - } else if (_mouseHidden) { - // if the mouse cursor is hidden, just look straight ahead - glm::vec3 rayOrigin, rayDirection; - _viewFrustum.computePickRay(0.5f, 0.5f, rayOrigin, rayDirection); - lookAtSpot = rayOrigin + rayDirection * FAR_AWAY_STARE; } else { - // just look in direction of the mouse ray - lookAtSpot = _mouseRayOrigin + _mouseRayDirection * FAR_AWAY_STARE; + // look in direction of the mouse ray, but use distance from intersection, if any + float distance = TREE_SCALE; + if (_myAvatar->getLookAtTargetAvatar()) { + distance = glm::distance(_mouseRayOrigin, + static_cast(_myAvatar->getLookAtTargetAvatar())->getHead().calculateAverageEyePosition()); + + } else if (_isHoverVoxel) { + distance = glm::distance(_mouseRayOrigin, getMouseVoxelWorldCoordinates(_hoverVoxel)); + } + lookAtSpot = _mouseRayOrigin + _mouseRayDirection * distance; } if (_faceshift.isActive()) { // deflect using Faceshift gaze data From a5636d2dc029e49a812f50a5ecb84ca30b3da9d1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 7 Feb 2014 11:52:37 -0800 Subject: [PATCH 29/42] make ThreadedAssignment subclasses handle QUdpSocket readyRead, closes #1895 --- assignment-client/src/Agent.cpp | 63 ++++++++------ assignment-client/src/Agent.h | 2 +- assignment-client/src/AssignmentClient.cpp | 86 +++++++++---------- assignment-client/src/audio/AudioMixer.cpp | 30 ++++--- assignment-client/src/audio/AudioMixer.h | 2 +- assignment-client/src/avatars/AvatarMixer.cpp | 73 ++++++++-------- assignment-client/src/avatars/AvatarMixer.h | 2 +- .../src/metavoxels/MetavoxelServer.cpp | 27 ++++-- .../src/metavoxels/MetavoxelServer.h | 2 +- assignment-client/src/octree/OctreeServer.cpp | 59 +++++++------ assignment-client/src/octree/OctreeServer.h | 2 +- libraries/shared/src/NodeList.cpp | 15 +++- libraries/shared/src/ThreadedAssignment.cpp | 13 +++ libraries/shared/src/ThreadedAssignment.h | 4 +- 14 files changed, 218 insertions(+), 162 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index eff573216a..0030e3ffb8 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -31,36 +31,43 @@ Agent::Agent(const QByteArray& packet) : _scriptEngine.getParticlesScriptingInterface()->setPacketSender(&_particleEditSender); } -void Agent::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr) { - PacketType datagramPacketType = packetTypeForPacket(dataByteArray); - if (datagramPacketType == PacketTypeJurisdiction) { - int headerBytes = numBytesForPacketHeader(dataByteArray); - - QUuid nodeUUID; - SharedNodePointer matchedNode = NodeList::getInstance()->nodeWithUUID(nodeUUID); - - if (matchedNode) { - // PacketType_JURISDICTION, first byte is the node type... - switch (dataByteArray[headerBytes]) { - case NodeType::VoxelServer: - _scriptEngine.getVoxelsScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(matchedNode, - dataByteArray); - break; - case NodeType::ParticleServer: - _scriptEngine.getParticlesScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(matchedNode, - dataByteArray); - break; +void Agent::readPendingDatagrams() { + QByteArray receivedPacket; + HifiSockAddr senderSockAddr; + NodeList* nodeList = NodeList::getInstance(); + + while (readAvailableDatagram(receivedPacket, senderSockAddr)) { + if (nodeList->packetVersionAndHashMatch(receivedPacket)) { + PacketType datagramPacketType = packetTypeForPacket(receivedPacket); + if (datagramPacketType == PacketTypeJurisdiction) { + int headerBytes = numBytesForPacketHeader(receivedPacket); + + SharedNodePointer matchedNode = nodeList->sendingNodeForPacket(receivedPacket); + + if (matchedNode) { + // PacketType_JURISDICTION, first byte is the node type... + switch (receivedPacket[headerBytes]) { + case NodeType::VoxelServer: + _scriptEngine.getVoxelsScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(matchedNode, + receivedPacket); + break; + case NodeType::ParticleServer: + _scriptEngine.getParticlesScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(matchedNode, + receivedPacket); + break; + } + } + + } else if (datagramPacketType == PacketTypeParticleAddResponse) { + // this will keep creatorTokenIDs to IDs mapped correctly + Particle::handleAddParticleResponse(receivedPacket); + + // also give our local particle tree a chance to remap any internal locally created particles + _particleTree.handleAddParticleResponse(receivedPacket); + } else { + NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket); } } - - } else if (datagramPacketType == PacketTypeParticleAddResponse) { - // this will keep creatorTokenIDs to IDs mapped correctly - Particle::handleAddParticleResponse(dataByteArray); - - // also give our local particle tree a chance to remap any internal locally created particles - _particleTree.handleAddParticleResponse(dataByteArray); - } else { - NodeList::getInstance()->processNodeData(senderSockAddr, dataByteArray); } } diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index 7495fc06bf..bc6b4f65fe 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -35,7 +35,7 @@ public: public slots: void run(); - void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr); + void readPendingDatagrams(); signals: void willSendAudioDataCallback(); void willSendVisualDataCallback(); diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 8add7d90f8..978882f358 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -90,8 +90,7 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : timer->start(ASSIGNMENT_REQUEST_INTERVAL_MSECS); // connect our readPendingDatagrams method to the readyRead() signal of the socket - connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams, - Qt::QueuedConnection); + connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams); } void AssignmentClient::sendAssignmentRequest() { @@ -112,49 +111,44 @@ void AssignmentClient::readPendingDatagrams() { senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer()); if (nodeList->packetVersionAndHashMatch(receivedPacket)) { - if (_currentAssignment) { - // have the threaded current assignment handle this datagram - QMetaObject::invokeMethod(_currentAssignment, "processDatagram", Qt::QueuedConnection, - Q_ARG(QByteArray, receivedPacket), - Q_ARG(HifiSockAddr, senderSockAddr)); - } else if (packetTypeForPacket(receivedPacket) == PacketTypeCreateAssignment) { + if (packetTypeForPacket(receivedPacket) == PacketTypeCreateAssignment) { + // construct the deployed assignment from the packet data + _currentAssignment = AssignmentFactory::unpackAssignment(receivedPacket); if (_currentAssignment) { - qDebug() << "Dropping received assignment since we are currently running one."; - } else { - // construct the deployed assignment from the packet data - _currentAssignment = AssignmentFactory::unpackAssignment(receivedPacket); + qDebug() << "Received an assignment -" << *_currentAssignment; - if (_currentAssignment) { - qDebug() << "Received an assignment -" << *_currentAssignment; - - // switch our nodelist domain IP and port to whoever sent us the assignment - - nodeList->setDomainSockAddr(senderSockAddr); - nodeList->setSessionUUID(_currentAssignment->getUUID()); - - qDebug() << "Destination IP for assignment is" << nodeList->getDomainIP().toString(); - - // start the deployed assignment - QThread* workerThread = new QThread(this); - - connect(workerThread, SIGNAL(started()), _currentAssignment, SLOT(run())); - - connect(_currentAssignment, SIGNAL(finished()), this, SLOT(assignmentCompleted())); - connect(_currentAssignment, SIGNAL(finished()), workerThread, SLOT(quit())); - connect(_currentAssignment, SIGNAL(finished()), _currentAssignment, SLOT(deleteLater())); - connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater())); - - _currentAssignment->moveToThread(workerThread); - - // move the NodeList to the thread used for the _current assignment - nodeList->moveToThread(workerThread); - - // Starts an event loop, and emits workerThread->started() - workerThread->start(); - } else { - qDebug() << "Received an assignment that could not be unpacked. Re-requesting."; - } + // switch our nodelist domain IP and port to whoever sent us the assignment + + nodeList->setDomainSockAddr(senderSockAddr); + nodeList->setSessionUUID(_currentAssignment->getUUID()); + + qDebug() << "Destination IP for assignment is" << nodeList->getDomainIP().toString(); + + // start the deployed assignment + QThread* workerThread = new QThread(this); + + connect(workerThread, SIGNAL(started()), _currentAssignment, SLOT(run())); + + connect(_currentAssignment, SIGNAL(finished()), this, SLOT(assignmentCompleted())); + connect(_currentAssignment, SIGNAL(finished()), workerThread, SLOT(quit())); + connect(_currentAssignment, SIGNAL(finished()), _currentAssignment, SLOT(deleteLater())); + connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater())); + + _currentAssignment->moveToThread(workerThread); + + // move the NodeList to the thread used for the _current assignment + nodeList->moveToThread(workerThread); + + // let the assignment handle the incoming datagrams for its duration + disconnect(&nodeList->getNodeSocket(), 0, this, 0); + connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, _currentAssignment, + &ThreadedAssignment::readPendingDatagrams); + + // Starts an event loop, and emits workerThread->started() + workerThread->start(); + } else { + qDebug() << "Received an assignment that could not be unpacked. Re-requesting."; } } else { // have the NodeList attempt to handle it @@ -170,10 +164,14 @@ void AssignmentClient::assignmentCompleted() { qDebug("Assignment finished or never started - waiting for new assignment."); - _currentAssignment = NULL; - NodeList* nodeList = NodeList::getInstance(); + // have us handle incoming NodeList datagrams again + disconnect(&nodeList->getNodeSocket(), 0, _currentAssignment, 0); + connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams); + + _currentAssignment = NULL; + // reset our NodeList by switching back to unassigned and clearing the list nodeList->setOwnerType(NodeType::Unassigned); nodeList->reset(); diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 6dbfb58f9a..30359f85c4 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -207,17 +207,25 @@ void AudioMixer::prepareMixForListeningNode(Node* node) { } -void AudioMixer::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr) { - // pull any new audio data from nodes off of the network stack - PacketType mixerPacketType = packetTypeForPacket(dataByteArray); - if (mixerPacketType == PacketTypeMicrophoneAudioNoEcho - || mixerPacketType == PacketTypeMicrophoneAudioWithEcho - || mixerPacketType == PacketTypeInjectAudio) { - - NodeList::getInstance()->findNodeAndUpdateWithDataFromPacket(dataByteArray); - } else { - // let processNodeData handle it. - NodeList::getInstance()->processNodeData(senderSockAddr, dataByteArray); +void AudioMixer::readPendingDatagrams() { + QByteArray receivedPacket; + HifiSockAddr senderSockAddr; + NodeList* nodeList = NodeList::getInstance(); + + while (readAvailableDatagram(receivedPacket, senderSockAddr)) { + if (nodeList->packetVersionAndHashMatch(receivedPacket)) { + // pull any new audio data from nodes off of the network stack + PacketType mixerPacketType = packetTypeForPacket(receivedPacket); + if (mixerPacketType == PacketTypeMicrophoneAudioNoEcho + || mixerPacketType == PacketTypeMicrophoneAudioWithEcho + || mixerPacketType == PacketTypeInjectAudio) { + + nodeList->findNodeAndUpdateWithDataFromPacket(receivedPacket); + } else { + // let processNodeData handle it. + nodeList->processNodeData(senderSockAddr, receivedPacket); + } + } } } diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index 2d42a6b629..e120d19d32 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -25,7 +25,7 @@ public slots: /// threaded run of assignment void run(); - void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr); + void readPendingDatagrams(); private: /// adds one buffer to the mix for a listening node void addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuffer* bufferToAdd, diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 5e0da14a59..c7989bc9e9 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -136,47 +136,52 @@ void AvatarMixer::nodeKilled(SharedNodePointer killedNode) { } } -void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr) { +void AvatarMixer::readPendingDatagrams() { + QByteArray receivedPacket; + HifiSockAddr senderSockAddr; NodeList* nodeList = NodeList::getInstance(); - switch (packetTypeForPacket(dataByteArray)) { - case PacketTypeAvatarData: { - nodeList->findNodeAndUpdateWithDataFromPacket(dataByteArray); - break; - } - case PacketTypeAvatarIdentity: { - - // check if we have a matching node in our list - SharedNodePointer avatarNode = nodeList->sendingNodeForPacket(dataByteArray); - - if (avatarNode && avatarNode->getLinkedData()) { - AvatarMixerClientData* nodeData = reinterpret_cast(avatarNode->getLinkedData()); - if (nodeData->hasIdentityChangedAfterParsing(dataByteArray) - && !nodeData->hasSentIdentityBetweenKeyFrames()) { - // this avatar changed their identity in some way and we haven't sent a packet in this keyframe - QByteArray identityPacket = byteArrayWithPopluatedHeader(PacketTypeAvatarIdentity); - - QByteArray individualByteArray = nodeData->identityByteArray(); - individualByteArray.replace(0, NUM_BYTES_RFC4122_UUID, avatarNode->getUUID().toRfc4122()); - - identityPacket.append(individualByteArray); - - nodeData->setHasSentIdentityBetweenKeyFrames(true); - nodeList->broadcastToNodes(identityPacket, NodeSet() << NodeType::Agent); + while (readAvailableDatagram(receivedPacket, senderSockAddr)) { + if (nodeList->packetVersionAndHashMatch(receivedPacket)) { + switch (packetTypeForPacket(receivedPacket)) { + case PacketTypeAvatarData: { + nodeList->findNodeAndUpdateWithDataFromPacket(receivedPacket); + break; } + case PacketTypeAvatarIdentity: { + + // check if we have a matching node in our list + SharedNodePointer avatarNode = nodeList->sendingNodeForPacket(receivedPacket); + + if (avatarNode && avatarNode->getLinkedData()) { + AvatarMixerClientData* nodeData = reinterpret_cast(avatarNode->getLinkedData()); + if (nodeData->hasIdentityChangedAfterParsing(receivedPacket) + && !nodeData->hasSentIdentityBetweenKeyFrames()) { + // this avatar changed their identity in some way and we haven't sent a packet in this keyframe + QByteArray identityPacket = byteArrayWithPopluatedHeader(PacketTypeAvatarIdentity); + + QByteArray individualByteArray = nodeData->identityByteArray(); + individualByteArray.replace(0, NUM_BYTES_RFC4122_UUID, avatarNode->getUUID().toRfc4122()); + + identityPacket.append(individualByteArray); + + nodeData->setHasSentIdentityBetweenKeyFrames(true); + nodeList->broadcastToNodes(identityPacket, NodeSet() << NodeType::Agent); + } + } + } + case PacketTypeKillAvatar: { + nodeList->processKillNode(receivedPacket); + break; + } + default: + // hand this off to the NodeList + nodeList->processNodeData(senderSockAddr, receivedPacket); + break; } } - case PacketTypeKillAvatar: { - nodeList->processKillNode(dataByteArray); - break; - } - default: - // hand this off to the NodeList - nodeList->processNodeData(senderSockAddr, dataByteArray); - break; } - } const qint64 AVATAR_IDENTITY_KEYFRAME_MSECS = 5000; diff --git a/assignment-client/src/avatars/AvatarMixer.h b/assignment-client/src/avatars/AvatarMixer.h index 61141411e6..acc5a178aa 100644 --- a/assignment-client/src/avatars/AvatarMixer.h +++ b/assignment-client/src/avatars/AvatarMixer.h @@ -23,7 +23,7 @@ public slots: void nodeAdded(SharedNodePointer nodeAdded); void nodeKilled(SharedNodePointer killedNode); - void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr); + void readPendingDatagrams(); }; #endif /* defined(__hifi__AvatarMixer__) */ diff --git a/assignment-client/src/metavoxels/MetavoxelServer.cpp b/assignment-client/src/metavoxels/MetavoxelServer.cpp index 3cd81d8ac7..4df72f5de9 100644 --- a/assignment-client/src/metavoxels/MetavoxelServer.cpp +++ b/assignment-client/src/metavoxels/MetavoxelServer.cpp @@ -41,15 +41,24 @@ void MetavoxelServer::run() { _sendTimer.start(SEND_INTERVAL); } -void MetavoxelServer::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr) { - switch (dataByteArray.at(0)) { - case PacketTypeMetavoxelData: - processData(dataByteArray, senderSockAddr); - break; - - default: - NodeList::getInstance()->processNodeData(senderSockAddr, dataByteArray); - break; +void MetavoxelServer::readPendingDatagrams() { + QByteArray receivedPacket; + HifiSockAddr senderSockAddr; + + NodeList* nodeList = NodeList::getInstance(); + + while (readAvailableDatagram(receivedPacket, senderSockAddr)) { + if (nodeList->packetVersionAndHashMatch(receivedPacket)) { + switch (packetTypeForPacket(receivedPacket)) { + case PacketTypeMetavoxelData: + processData(receivedPacket, senderSockAddr); + break; + + default: + NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket); + break; + } + } } } diff --git a/assignment-client/src/metavoxels/MetavoxelServer.h b/assignment-client/src/metavoxels/MetavoxelServer.h index f106bd3494..5ee861b75d 100644 --- a/assignment-client/src/metavoxels/MetavoxelServer.h +++ b/assignment-client/src/metavoxels/MetavoxelServer.h @@ -39,7 +39,7 @@ public: virtual void run(); - virtual void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr); + virtual void readPendingDatagrams(); private slots: diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 1b66c9ddba..7d237f46e2 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -458,36 +458,43 @@ void OctreeServer::parsePayload() { } } -void OctreeServer::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr) { - NodeList* nodeList = NodeList::getInstance(); - - PacketType packetType = packetTypeForPacket(dataByteArray); +void OctreeServer::readPendingDatagrams() { + QByteArray receivedPacket; + HifiSockAddr senderSockAddr; - SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(dataByteArray); - - if (packetType == getMyQueryMessageType()) { - bool debug = false; - if (debug) { - qDebug() << "Got PacketTypeVoxelQuery at" << usecTimestampNow(); - } - - // If we got a PacketType_VOXEL_QUERY, then we're talking to an NodeType_t_AVATAR, and we - // need to make sure we have it in our nodeList. - if (matchingNode) { - nodeList->updateNodeWithDataFromPacket(matchingNode, dataByteArray); + NodeList* nodeList = NodeList::getInstance(); + + while (readAvailableDatagram(receivedPacket, senderSockAddr)) { + if (nodeList->packetVersionAndHashMatch(receivedPacket)) { + PacketType packetType = packetTypeForPacket(receivedPacket); - OctreeQueryNode* nodeData = (OctreeQueryNode*) matchingNode->getLinkedData(); - if (nodeData && !nodeData->isOctreeSendThreadInitalized()) { - nodeData->initializeOctreeSendThread(this, matchingNode->getUUID()); + SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket); + + if (packetType == getMyQueryMessageType()) { + bool debug = false; + if (debug) { + qDebug() << "Got PacketTypeVoxelQuery at" << usecTimestampNow(); + } + + // If we got a PacketType_VOXEL_QUERY, then we're talking to an NodeType_t_AVATAR, and we + // need to make sure we have it in our nodeList. + if (matchingNode) { + nodeList->updateNodeWithDataFromPacket(matchingNode, receivedPacket); + + OctreeQueryNode* nodeData = (OctreeQueryNode*) matchingNode->getLinkedData(); + if (nodeData && !nodeData->isOctreeSendThreadInitalized()) { + nodeData->initializeOctreeSendThread(this, matchingNode->getUUID()); + } + } + } else if (packetType == PacketTypeJurisdictionRequest) { + _jurisdictionSender->queueReceivedPacket(matchingNode, receivedPacket); + } else if (_octreeInboundPacketProcessor && getOctree()->handlesEditPacketType(packetType)) { + _octreeInboundPacketProcessor->queueReceivedPacket(matchingNode, receivedPacket); + } else { + // let processNodeData handle it. + NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket); } } - } else if (packetType == PacketTypeJurisdictionRequest) { - _jurisdictionSender->queueReceivedPacket(matchingNode, dataByteArray); - } else if (_octreeInboundPacketProcessor && getOctree()->handlesEditPacketType(packetType)) { - _octreeInboundPacketProcessor->queueReceivedPacket(matchingNode, dataByteArray); - } else { - // let processNodeData handle it. - NodeList::getInstance()->processNodeData(senderSockAddr, dataByteArray); } } diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index 26c39d1a1d..e221011b76 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -67,7 +67,7 @@ public: public slots: /// runs the voxel server assignment void run(); - void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr); + void readPendingDatagrams(); protected: void parsePayload(); diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index ba890564ce..43f3240b12 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -94,7 +94,12 @@ bool NodeList::packetVersionAndHashMatch(const QByteArray& packet) { << qPrintable(QString::number(versionForPacketType(mismatchType))) << "expected."; } - if (packetTypeForPacket(packet) != PacketTypeDomainList && packetTypeForPacket(packet) != PacketTypeDomainListRequest) { + const QSet NON_VERIFIED_PACKETS = QSet() << PacketTypeDomainList + << PacketTypeDomainListRequest << PacketTypeStunResponse << PacketTypeDataServerConfirm + << PacketTypeDataServerGet << PacketTypeDataServerPut << PacketTypeDataServerSend + << PacketTypeCreateAssignment << PacketTypeRequestAssignment; + + if (!NON_VERIFIED_PACKETS.contains(packetTypeForPacket(packet))) { // figure out which node this is from SharedNodePointer sendingNode = sendingNodeForPacket(packet); if (sendingNode) { @@ -102,13 +107,15 @@ bool NodeList::packetVersionAndHashMatch(const QByteArray& packet) { if (hashFromPacketHeader(packet) == hashForPacketAndConnectionUUID(packet, sendingNode->getConnectionSecret())) { return true; } else { - qDebug() << "Packet hash mismatch" << packetTypeForPacket(packet) << "received from known node with UUID" - << uuidFromPacketHeader(packet); + qDebug() << "Packet hash mismatch on" << packetTypeForPacket(packet) << "- Sender" + << uuidFromPacketHeader(packet); } } else { qDebug() << "Packet of type" << packetTypeForPacket(packet) << "received from unknown node with UUID" - << uuidFromPacketHeader(packet); + << uuidFromPacketHeader(packet); } + } else { + return true; } return false; diff --git a/libraries/shared/src/ThreadedAssignment.cpp b/libraries/shared/src/ThreadedAssignment.cpp index 2c1110491b..5f66ae4a4e 100644 --- a/libraries/shared/src/ThreadedAssignment.cpp +++ b/libraries/shared/src/ThreadedAssignment.cpp @@ -60,3 +60,16 @@ void ThreadedAssignment::checkInWithDomainServerOrExit() { NodeList::getInstance()->sendDomainServerCheckIn(); } } + +bool ThreadedAssignment::readAvailableDatagram(QByteArray& destinationByteArray, HifiSockAddr& senderSockAddr) { + NodeList* nodeList = NodeList::getInstance(); + + if (nodeList->getNodeSocket().hasPendingDatagrams()) { + destinationByteArray.resize(nodeList->getNodeSocket().pendingDatagramSize()); + nodeList->getNodeSocket().readDatagram(destinationByteArray.data(), destinationByteArray.size(), + senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer()); + return true; + } else { + return false; + } +} diff --git a/libraries/shared/src/ThreadedAssignment.h b/libraries/shared/src/ThreadedAssignment.h index 7c7aa9a63e..c8aa1c419c 100644 --- a/libraries/shared/src/ThreadedAssignment.h +++ b/libraries/shared/src/ThreadedAssignment.h @@ -23,8 +23,10 @@ public slots: virtual void deleteLater(); - virtual void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr) = 0; + virtual void readPendingDatagrams() = 0; protected: + bool readAvailableDatagram(QByteArray& destinationByteArray, HifiSockAddr& senderSockAddr); + void commonInit(const char* targetName, NodeType_t nodeType); bool _isFinished; private slots: From 3ad8e7260e68163057352c9b1acbeed9a387e643 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 7 Feb 2014 13:42:52 -0800 Subject: [PATCH 30/42] fix an accidental DOS and remove getNodeActiveSocketOrPing API --- interface/src/Audio.cpp | 2 +- interface/src/ui/VoxelStatsDialog.cpp | 2 +- libraries/octree/src/JurisdictionListener.cpp | 2 +- .../octree/src/OctreeEditPacketSender.cpp | 22 +++++++++---------- libraries/shared/src/NodeList.cpp | 19 ++++++---------- libraries/shared/src/NodeList.h | 2 -- libraries/shared/src/PacketHeaders.cpp | 6 ++--- 7 files changed, 23 insertions(+), 32 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index e7fdcd32c7..9dd3c0377f 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -388,7 +388,7 @@ void Audio::handleAudioInput() { NodeList* nodeList = NodeList::getInstance(); SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer); - if (audioMixer && nodeList->getNodeActiveSocketOrPing(audioMixer)) { + if (audioMixer && audioMixer->getActiveSocket()) { MyAvatar* interfaceAvatar = Application::getInstance()->getAvatar(); glm::vec3 headPosition = interfaceAvatar->getHead().getPosition(); glm::quat headOrientation = interfaceAvatar->getHead().getOrientation(); diff --git a/interface/src/ui/VoxelStatsDialog.cpp b/interface/src/ui/VoxelStatsDialog.cpp index 1d94705504..0ac0a2b933 100644 --- a/interface/src/ui/VoxelStatsDialog.cpp +++ b/interface/src/ui/VoxelStatsDialog.cpp @@ -265,7 +265,7 @@ void VoxelStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t serv std::stringstream extraDetails(""); std::stringstream linkDetails(""); - if (nodeList->getNodeActiveSocketOrPing(node)) { + if (node->getActiveSocket()) { serverDetails << "active "; } else { serverDetails << "inactive "; diff --git a/libraries/octree/src/JurisdictionListener.cpp b/libraries/octree/src/JurisdictionListener.cpp index a15c72cc5e..20e5af012f 100644 --- a/libraries/octree/src/JurisdictionListener.cpp +++ b/libraries/octree/src/JurisdictionListener.cpp @@ -45,7 +45,7 @@ bool JurisdictionListener::queueJurisdictionRequest() { NodeList* nodeList = NodeList::getInstance(); foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { - if (nodeList->getNodeActiveSocketOrPing(node) && node->getType() == getNodeType()) { + if (node->getType() == getNodeType() && node->getActiveSocket()) { _packetSender.queuePacketForSending(node, QByteArray(reinterpret_cast(bufferOut), sizeOut)); nodeCount++; } diff --git a/libraries/octree/src/OctreeEditPacketSender.cpp b/libraries/octree/src/OctreeEditPacketSender.cpp index ca3ffc707f..1c1ed13f8d 100644 --- a/libraries/octree/src/OctreeEditPacketSender.cpp +++ b/libraries/octree/src/OctreeEditPacketSender.cpp @@ -60,19 +60,17 @@ bool OctreeEditPacketSender::serversExist() const { foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { // only send to the NodeTypes that are getMyNodeType() - if (node->getType() == getMyNodeType()) { - if (nodeList->getNodeActiveSocketOrPing(node)) { - QUuid nodeUUID = node->getUUID(); - // If we've got Jurisdictions set, then check to see if we know the jurisdiction for this server - if (_serverJurisdictions) { - // lookup our nodeUUID in the jurisdiction map, if it's missing then we're - // missing at least one jurisdiction - if ((*_serverJurisdictions).find(nodeUUID) == (*_serverJurisdictions).end()) { - atLeastOnJurisdictionMissing = true; - } + if (node->getType() == getMyNodeType() && node->getActiveSocket()) { + QUuid nodeUUID = node->getUUID(); + // If we've got Jurisdictions set, then check to see if we know the jurisdiction for this server + if (_serverJurisdictions) { + // lookup our nodeUUID in the jurisdiction map, if it's missing then we're + // missing at least one jurisdiction + if ((*_serverJurisdictions).find(nodeUUID) == (*_serverJurisdictions).end()) { + atLeastOnJurisdictionMissing = true; } - hasServers = true; } + hasServers = true; } if (atLeastOnJurisdictionMissing) { break; // no point in looking further... @@ -91,7 +89,7 @@ void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned c // only send to the NodeTypes that are getMyNodeType() if (node->getType() == getMyNodeType() && ((node->getUUID() == nodeUUID) || (nodeUUID.isNull()))) { - if (nodeList->getNodeActiveSocketOrPing(node)) { + if (node->getActiveSocket()) { queuePacketForSending(node, QByteArray(reinterpret_cast(buffer), length)); // debugging output... diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 43f3240b12..0dc94a20b3 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -127,7 +127,7 @@ qint64 NodeList::writeDatagram(const QByteArray& datagram, const SharedNodePoint // if we don't have an ovveriden address, assume they want to send to the node's active socket const HifiSockAddr* destinationSockAddr = &overridenSockAddr; if (overridenSockAddr.isNull()) { - if (getNodeActiveSocketOrPing(destinationNode)) { + if (destinationNode->getActiveSocket()) { // use the node's active socket as the destination socket destinationSockAddr = destinationNode->getActiveSocket(); } else { @@ -140,6 +140,8 @@ qint64 NodeList::writeDatagram(const QByteArray& datagram, const SharedNodePoint // setup the MD5 hash for source verification in the header replaceHashInPacketGivenConnectionUUID(datagramCopy, destinationNode->getConnectionSecret()); + qDebug() << "Sending a packet of type" << packetTypeForPacket(datagram); + return _nodeSocket.writeDatagram(datagramCopy, destinationSockAddr->getAddress(), destinationSockAddr->getPort()); } @@ -680,8 +682,11 @@ SharedNodePointer NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket); SharedNodePointer newNodeSharedPointer(newNode, &QObject::deleteLater); + // try and ping the new node right away to open a connection + pingPublicAndLocalSocketsForInactiveNode(newNodeSharedPointer); + _nodeHash.insert(newNode->getUUID(), newNodeSharedPointer); - + _nodeHashMutex.unlock(); qDebug() << "Added" << *newNode; @@ -740,16 +745,6 @@ void NodeList::pingInactiveNodes() { } } -const HifiSockAddr* NodeList::getNodeActiveSocketOrPing(const SharedNodePointer& node) { - if (node && node->getActiveSocket()) { - return node->getActiveSocket(); - } else if (node) { - pingPublicAndLocalSocketsForInactiveNode(node); - } - - return NULL; -} - void NodeList::activateSocketFromNodeCommunication(const QByteArray& packet, const SharedNodePointer& sendingNode) { // deconstruct this ping packet to see if it is a public or local reply QDataStream packetStream(packet); diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 408459e51f..b6afd21451 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -129,8 +129,6 @@ public: void loadData(QSettings* settings); void saveData(QSettings* settings); - - const HifiSockAddr* getNodeActiveSocketOrPing(const SharedNodePointer& node); public slots: void sendDomainServerCheckIn(); void pingInactiveNodes(); diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index 7193b6f648..d4049e7310 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -105,12 +105,12 @@ QUuid uuidFromPacketHeader(const QByteArray& packet) { } QByteArray hashFromPacketHeader(const QByteArray& packet) { - return packet.mid(NUM_STATIC_HEADER_BYTES - NUM_BYTES_MD5_HASH, NUM_BYTES_MD5_HASH); + return packet.mid(numBytesForPacketHeader(packet) - NUM_BYTES_MD5_HASH, NUM_BYTES_MD5_HASH); } QByteArray hashForPacketAndConnectionUUID(const QByteArray& packet, const QUuid& connectionUUID) { - return QCryptographicHash::hash(packet.mid(numBytesForPacketHeader(packet)) - + connectionUUID.toRfc4122(), QCryptographicHash::Md5); + return QCryptographicHash::hash(packet.mid(numBytesForPacketHeader(packet)) + connectionUUID.toRfc4122(), + QCryptographicHash::Md5); } void replaceHashInPacketGivenConnectionUUID(QByteArray& packet, const QUuid& connectionUUID) { From 7c6d3cd01f82dfa02758da9ac3487e179308ce19 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 7 Feb 2014 13:46:59 -0800 Subject: [PATCH 31/42] fix broken build from NetworkPacket --- libraries/shared/src/NetworkPacket.cpp | 4 +++- libraries/shared/src/NetworkPacket.h | 4 +--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/shared/src/NetworkPacket.cpp b/libraries/shared/src/NetworkPacket.cpp index bc4f8f8cd8..1671dc2435 100644 --- a/libraries/shared/src/NetworkPacket.cpp +++ b/libraries/shared/src/NetworkPacket.cpp @@ -8,9 +8,11 @@ // A really simple class that stores a network packet between being received and being processed // +#include #include #include -#include + +#include "SharedUtil.h" #include "NetworkPacket.h" diff --git a/libraries/shared/src/NetworkPacket.h b/libraries/shared/src/NetworkPacket.h index be15d31ee2..0875b9f131 100644 --- a/libraries/shared/src/NetworkPacket.h +++ b/libraries/shared/src/NetworkPacket.h @@ -18,9 +18,7 @@ #include #endif -#include "HifiSockAddr.h" - -#include "SharedUtil.h" // for MAX_PACKET_SIZE +#include "NodeList.h" /// Storage of not-yet processed inbound, or not yet sent outbound generic UDP network packet class NetworkPacket { From 72a3e6f22c4ccf6e2b163284ae77d050cb781540 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 7 Feb 2014 13:49:59 -0800 Subject: [PATCH 32/42] fix long column in NodeList --- libraries/shared/src/NodeList.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 257c4a0ea7..ca4e8ab7b4 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -114,7 +114,8 @@ public: SharedNodePointer nodeWithUUID(const QUuid& nodeUUID); SharedNodePointer sendingNodeForPacket(const QByteArray& packet); - SharedNodePointer addOrUpdateNode(const QUuid& uuid, char nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket); + SharedNodePointer addOrUpdateNode(const QUuid& uuid, char nodeType, + const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket); void processNodeData(const HifiSockAddr& senderSockAddr, const QByteArray& packet); void processKillNode(const QByteArray& datagram); From dd4d944dea44a639742ce9193a4e363363fb2971 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 7 Feb 2014 14:06:42 -0800 Subject: [PATCH 33/42] ping inactive nodes in conjunction with domain server check in --- assignment-client/src/Agent.cpp | 4 ---- assignment-client/src/octree/OctreeServer.cpp | 4 ---- interface/src/DatagramProcessor.cpp | 2 +- libraries/shared/src/NodeList.cpp | 14 +++++++------- 4 files changed, 8 insertions(+), 16 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 0030e3ffb8..cc0ddd59f2 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -107,10 +107,6 @@ void Agent::run() { connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes())); silentNodeTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000); - QTimer* pingNodesTimer = new QTimer(this); - connect(pingNodesTimer, SIGNAL(timeout()), nodeList, SLOT(pingInactiveNodes())); - pingNodesTimer->start(PING_INACTIVE_NODE_INTERVAL_USECS / 1000); - // tell our script engine about our local particle tree _scriptEngine.getParticlesScriptingInterface()->setParticleTree(&_particleTree); diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 7d237f46e2..1fb858c884 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -655,8 +655,4 @@ void OctreeServer::run() { QTimer* silentNodeTimer = new QTimer(this); connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes())); silentNodeTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000); - - QTimer* pingNodesTimer = new QTimer(this); - connect(pingNodesTimer, SIGNAL(timeout()), nodeList, SLOT(pingInactiveNodes())); - pingNodesTimer->start(PING_INACTIVE_NODE_INTERVAL_USECS / 1000); } diff --git a/interface/src/DatagramProcessor.cpp b/interface/src/DatagramProcessor.cpp index 6271ef5fde..d8447168cd 100644 --- a/interface/src/DatagramProcessor.cpp +++ b/interface/src/DatagramProcessor.cpp @@ -121,7 +121,7 @@ void DatagramProcessor::processDatagrams() { DataServerClient::processMessageFromDataServer(incomingPacket); break; default: - NodeList::getInstance()->processNodeData(senderSockAddr, incomingPacket); + nodeList->processNodeData(senderSockAddr, incomingPacket); break; } } diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 0dc94a20b3..2e78537734 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -140,8 +140,6 @@ qint64 NodeList::writeDatagram(const QByteArray& datagram, const SharedNodePoint // setup the MD5 hash for source verification in the header replaceHashInPacketGivenConnectionUUID(datagramCopy, destinationNode->getConnectionSecret()); - qDebug() << "Sending a packet of type" << packetTypeForPacket(datagram); - return _nodeSocket.writeDatagram(datagramCopy, destinationSockAddr->getAddress(), destinationSockAddr->getPort()); } @@ -234,9 +232,10 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr } case PacketTypePing: { // send back a reply - if (sendingNodeForPacket(packet)) { + SharedNodePointer matchingNode = sendingNodeForPacket(packet); + if (matchingNode) { QByteArray replyPacket = constructPingReplyPacket(packet); - writeDatagram(replyPacket, sendingNodeForPacket(packet), senderSockAddr); + writeDatagram(replyPacket, matchingNode, senderSockAddr); } break; @@ -608,6 +607,10 @@ int NodeList::processDomainServerList(const QByteArray& packet) { packetStream >> connectionUUID; node->setConnectionSecret(connectionUUID); } + + // ping inactive nodes in conjunction with receipt of list from domain-server + // this makes it happen every second and also pings any newly added nodes + pingInactiveNodes(); return readNodes; } @@ -681,9 +684,6 @@ SharedNodePointer NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, // we didn't have this node, so add them Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket); SharedNodePointer newNodeSharedPointer(newNode, &QObject::deleteLater); - - // try and ping the new node right away to open a connection - pingPublicAndLocalSocketsForInactiveNode(newNodeSharedPointer); _nodeHash.insert(newNode->getUUID(), newNodeSharedPointer); From 3bf0ed719cac007807bf279fe7dff091ca9dc8c1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 7 Feb 2014 14:08:42 -0800 Subject: [PATCH 34/42] remove a comment in HifiSockAddr --- libraries/shared/src/HifiSockAddr.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/shared/src/HifiSockAddr.cpp b/libraries/shared/src/HifiSockAddr.cpp index 44eedc6b17..cc031525d8 100644 --- a/libraries/shared/src/HifiSockAddr.cpp +++ b/libraries/shared/src/HifiSockAddr.cpp @@ -45,8 +45,6 @@ HifiSockAddr::HifiSockAddr(const QString& hostname, quint16 hostOrderPort) { } HifiSockAddr& HifiSockAddr::operator=(const HifiSockAddr& rhsSockAddr) { - //HifiSockAddr temp(rhsSockAddr); - //swap(temp); _address = rhsSockAddr._address; _port = rhsSockAddr._port; From a1a4a3db8a1aa7cce6ca5c5075bd3fcfa86a2732 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 7 Feb 2014 14:27:10 -0800 Subject: [PATCH 35/42] HifiSockAddr to SharedNodePointer changes in MetavoxelServer --- .../src/metavoxels/MetavoxelServer.cpp | 34 +++++++++++-------- .../src/metavoxels/MetavoxelServer.h | 8 ++--- interface/src/MetavoxelSystem.cpp | 4 +-- interface/src/MetavoxelSystem.h | 2 +- libraries/metavoxels/src/MetavoxelUtil.cpp | 4 +-- libraries/metavoxels/src/MetavoxelUtil.h | 3 +- libraries/shared/src/DataServerClient.cpp | 2 +- 7 files changed, 31 insertions(+), 26 deletions(-) diff --git a/assignment-client/src/metavoxels/MetavoxelServer.cpp b/assignment-client/src/metavoxels/MetavoxelServer.cpp index 4df72f5de9..fa934142d3 100644 --- a/assignment-client/src/metavoxels/MetavoxelServer.cpp +++ b/assignment-client/src/metavoxels/MetavoxelServer.cpp @@ -50,10 +50,13 @@ void MetavoxelServer::readPendingDatagrams() { while (readAvailableDatagram(receivedPacket, senderSockAddr)) { if (nodeList->packetVersionAndHashMatch(receivedPacket)) { switch (packetTypeForPacket(receivedPacket)) { - case PacketTypeMetavoxelData: - processData(receivedPacket, senderSockAddr); + case PacketTypeMetavoxelData: { + SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket); + if (matchingNode) { + processData(receivedPacket, matchingNode); + } break; - + } default: NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket); break; @@ -76,10 +79,10 @@ void MetavoxelServer::sendDeltas() { _sendTimer.start(qMax(0, 2 * SEND_INTERVAL - elapsed)); } -void MetavoxelServer::processData(const QByteArray& data, const HifiSockAddr& sender) { +void MetavoxelServer::processData(const QByteArray& data, const SharedNodePointer& sendingNode) { // read the session id int headerPlusIDSize; - QUuid sessionID = readSessionID(data, sender, headerPlusIDSize); + QUuid sessionID = readSessionID(data, sendingNode, headerPlusIDSize); if (sessionID.isNull()) { return; } @@ -87,18 +90,19 @@ void MetavoxelServer::processData(const QByteArray& data, const HifiSockAddr& se // forward to session, creating if necessary MetavoxelSession*& session = _sessions[sessionID]; if (!session) { - session = new MetavoxelSession(this, sessionID, QByteArray::fromRawData(data.constData(), headerPlusIDSize), sender); + session = new MetavoxelSession(this, sessionID, QByteArray::fromRawData(data.constData(), headerPlusIDSize), + sendingNode); } - session->receivedData(data, sender); + session->receivedData(data, sendingNode); } MetavoxelSession::MetavoxelSession(MetavoxelServer* server, const QUuid& sessionId, - const QByteArray& datagramHeader, const HifiSockAddr& sender) : + const QByteArray& datagramHeader, const SharedNodePointer& sendingNode) : QObject(server), _server(server), _sessionId(sessionId), _sequencer(datagramHeader), - _sender(sender) { + _sendingNode(sendingNode) { const int TIMEOUT_INTERVAL = 30 * 1000; _timeoutTimer.setInterval(TIMEOUT_INTERVAL); @@ -114,15 +118,15 @@ MetavoxelSession::MetavoxelSession(MetavoxelServer* server, const QUuid& session SendRecord record = { 0 }; _sendRecords.append(record); - qDebug() << "Opened session [sessionId=" << _sessionId << ", sender=" << _sender << "]"; + qDebug() << "Opened session [sessionId=" << _sessionId << ", sendingNode=" << sendingNode << "]"; } -void MetavoxelSession::receivedData(const QByteArray& data, const HifiSockAddr& sender) { +void MetavoxelSession::receivedData(const QByteArray& data, const SharedNodePointer& sendingNode) { // reset the timeout timer _timeoutTimer.start(); // save the most recent sender - _sender = sender; + _sendingNode = sendingNode; // process through sequencer _sequencer.receivedDatagram(data); @@ -140,12 +144,12 @@ void MetavoxelSession::sendDelta() { } void MetavoxelSession::timedOut() { - qDebug() << "Session timed out [sessionId=" << _sessionId << ", sender=" << _sender << "]"; + qDebug() << "Session timed out [sessionId=" << _sessionId << ", sendingNode=" << _sendingNode << "]"; _server->removeSession(_sessionId); } void MetavoxelSession::sendData(const QByteArray& data) { - NodeList::getInstance()->getNodeSocket().writeDatagram(data, _sender.getAddress(), _sender.getPort()); + NodeList::getInstance()->writeDatagram(data, _sendingNode); } void MetavoxelSession::readPacket(Bitstream& in) { @@ -161,7 +165,7 @@ void MetavoxelSession::clearSendRecordsBefore(int index) { void MetavoxelSession::handleMessage(const QVariant& message) { int userType = message.userType(); if (userType == CloseSessionMessage::Type) { - qDebug() << "Session closed [sessionId=" << _sessionId << ", sender=" << _sender << "]"; + qDebug() << "Session closed [sessionId=" << _sessionId << ", sendingNode=" << _sendingNode << "]"; _server->removeSession(_sessionId); } else if (userType == ClientStateMessage::Type) { diff --git a/assignment-client/src/metavoxels/MetavoxelServer.h b/assignment-client/src/metavoxels/MetavoxelServer.h index 5ee861b75d..60fdeca5a5 100644 --- a/assignment-client/src/metavoxels/MetavoxelServer.h +++ b/assignment-client/src/metavoxels/MetavoxelServer.h @@ -47,7 +47,7 @@ private slots: private: - void processData(const QByteArray& data, const HifiSockAddr& sender); + void processData(const QByteArray& data, const SharedNodePointer& sendingNode); QTimer _sendTimer; qint64 _lastSend; @@ -64,9 +64,9 @@ class MetavoxelSession : public QObject { public: MetavoxelSession(MetavoxelServer* server, const QUuid& sessionId, - const QByteArray& datagramHeader, const HifiSockAddr& sender); + const QByteArray& datagramHeader, const SharedNodePointer& sendingNode); - void receivedData(const QByteArray& data, const HifiSockAddr& sender); + void receivedData(const QByteArray& data, const SharedNodePointer& sendingNode); void sendDelta(); @@ -96,7 +96,7 @@ private: QTimer _timeoutTimer; DatagramSequencer _sequencer; - HifiSockAddr _sender; + SharedNodePointer _sendingNode; glm::vec3 _position; diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index b6b45a2f99..34c3be5308 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -144,9 +144,9 @@ void MetavoxelSystem::removeClient(const QUuid& uuid) { delete client; } -void MetavoxelSystem::receivedData(const QByteArray& data, const HifiSockAddr& sender) { +void MetavoxelSystem::receivedData(const QByteArray& data, const SharedNodePointer& sendingNode) { int headerPlusIDSize; - QUuid sessionID = readSessionID(data, sender, headerPlusIDSize); + QUuid sessionID = readSessionID(data, sendingNode, headerPlusIDSize); if (sessionID.isNull()) { return; } diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index 0956a9d0d3..7bb7935e4d 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -52,7 +52,7 @@ private: Q_INVOKABLE void addClient(const SharedNodePointer& node); Q_INVOKABLE void removeClient(const QUuid& uuid); - Q_INVOKABLE void receivedData(const QByteArray& data, const HifiSockAddr& sender); + Q_INVOKABLE void receivedData(const QByteArray& data, const SharedNodePointer& sendingNode); class Point { public: diff --git a/libraries/metavoxels/src/MetavoxelUtil.cpp b/libraries/metavoxels/src/MetavoxelUtil.cpp index e762fd06e0..e59cf0fe21 100644 --- a/libraries/metavoxels/src/MetavoxelUtil.cpp +++ b/libraries/metavoxels/src/MetavoxelUtil.cpp @@ -106,7 +106,7 @@ static QItemEditorCreatorBase* qColorEditorCreator = createQColorEditorCreator() static QItemEditorCreatorBase* vec3EditorCreator = createVec3EditorCreator(); static QItemEditorCreatorBase* parameterizedURLEditorCreator = createParameterizedURLEditorCreator(); -QUuid readSessionID(const QByteArray& data, const HifiSockAddr& sender, int& headerPlusIDSize) { +QUuid readSessionID(const QByteArray& data, const SharedNodePointer& sendingNode, int& headerPlusIDSize) { // get the header size int headerSize = numBytesForPacketHeader(data); @@ -114,7 +114,7 @@ QUuid readSessionID(const QByteArray& data, const HifiSockAddr& sender, int& hea const int UUID_BYTES = 16; headerPlusIDSize = headerSize + UUID_BYTES; if (data.size() < headerPlusIDSize) { - qWarning() << "Metavoxel data too short [size=" << data.size() << ", sender=" << sender << "]\n"; + qWarning() << "Metavoxel data too short [size=" << data.size() << ", sendingNode=" << sendingNode << "]\n"; return QUuid(); } return QUuid::fromRfc4122(QByteArray::fromRawData(data.constData() + headerSize, UUID_BYTES)); diff --git a/libraries/metavoxels/src/MetavoxelUtil.h b/libraries/metavoxels/src/MetavoxelUtil.h index 117825be64..9fa721d21c 100644 --- a/libraries/metavoxels/src/MetavoxelUtil.h +++ b/libraries/metavoxels/src/MetavoxelUtil.h @@ -15,6 +15,7 @@ #include #include +#include #include #include "Bitstream.h" @@ -30,7 +31,7 @@ class NetworkProgram; /// Reads and returns the session ID from a datagram. /// \param[out] headerPlusIDSize the size of the header (including the session ID) within the data /// \return the session ID, or a null ID if invalid (in which case a warning will be logged) -QUuid readSessionID(const QByteArray& data, const HifiSockAddr& sender, int& headerPlusIDSize); +QUuid readSessionID(const QByteArray& data, const SharedNodePointer& sendingNode, int& headerPlusIDSize); /// A streamable axis-aligned bounding box. class Box { diff --git a/libraries/shared/src/DataServerClient.cpp b/libraries/shared/src/DataServerClient.cpp index fd003aa3bb..7ca951ba29 100644 --- a/libraries/shared/src/DataServerClient.cpp +++ b/libraries/shared/src/DataServerClient.cpp @@ -21,7 +21,7 @@ quint8 DataServerClient::_sequenceNumber = 0; const char MULTI_KEY_VALUE_SEPARATOR = '|'; -const char DATA_SERVER_HOSTNAME[] = "data.highfidelity.io"; +const char DATA_SERVER_HOSTNAME[] = "localhost"; const unsigned short DATA_SERVER_PORT = 3282; const HifiSockAddr& DataServerClient::dataServerSockAddr() { From f945aac5cd5e7a51133431aac96c507169ce7b35 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 7 Feb 2014 14:32:09 -0800 Subject: [PATCH 36/42] bump version on unverified packets whose header format has changed --- libraries/shared/src/PacketHeaders.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index d4049e7310..b46a57d4aa 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -46,6 +46,17 @@ PacketVersion versionForPacketType(PacketType type) { switch (type) { case PacketTypeParticleData: return 1; + case PacketTypeDomainList: + case PacketTypeDomainListRequest: + return 1; + case PacketTypeCreateAssignment: + case PacketTypeRequestAssignment: + return 1; + case PacketTypeDataServerGet: + case PacketTypeDataServerPut: + case PacketTypeDataServerConfirm: + case PacketTypeDataServerSend: + return 1; default: return 0; } From 3e13608e19f0bb04452d0fd8430900dd2890d7f3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 7 Feb 2014 15:06:57 -0800 Subject: [PATCH 37/42] switch back to proper data-server --- libraries/shared/src/DataServerClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/DataServerClient.cpp b/libraries/shared/src/DataServerClient.cpp index 7ca951ba29..fd003aa3bb 100644 --- a/libraries/shared/src/DataServerClient.cpp +++ b/libraries/shared/src/DataServerClient.cpp @@ -21,7 +21,7 @@ quint8 DataServerClient::_sequenceNumber = 0; const char MULTI_KEY_VALUE_SEPARATOR = '|'; -const char DATA_SERVER_HOSTNAME[] = "localhost"; +const char DATA_SERVER_HOSTNAME[] = "data.highfidelity.io"; const unsigned short DATA_SERVER_PORT = 3282; const HifiSockAddr& DataServerClient::dataServerSockAddr() { From f237b77fa7a86f8ec258c9dd592fe36ef7300e2c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 7 Feb 2014 15:26:18 -0800 Subject: [PATCH 38/42] fix a bad cast to Assignment, closes #1935 --- domain-server/resources/web/js/tables.js | 2 +- domain-server/src/DomainServer.cpp | 19 ++++++++++--------- domain-server/src/DomainServer.h | 3 +++ 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/domain-server/resources/web/js/tables.js b/domain-server/resources/web/js/tables.js index 390beaa89a..d0855d7967 100644 --- a/domain-server/resources/web/js/tables.js +++ b/domain-server/resources/web/js/tables.js @@ -23,8 +23,8 @@ $(document).ready(function(){ $.each(json.queued, function (uuid, data) { queuedTableBody += ""; - queuedTableBody += "" + uuid + ""; queuedTableBody += "" + data.type + ""; + queuedTableBody += "" + uuid + ""; queuedTableBody += "" + (data.pool ? data.pool : "") + ""; queuedTableBody += ""; }); diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 2a98c9b8b0..05a1b4ea65 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -374,7 +374,7 @@ void DomainServer::readAvailableDatagrams() { } } -QJsonObject jsonForSocket(const HifiSockAddr& socket) { +QJsonObject DomainServer::jsonForSocket(const HifiSockAddr& socket) { QJsonObject socketJSON; socketJSON["ip"] = socket.getAddress().toString(); @@ -388,7 +388,7 @@ const char JSON_KEY_PUBLIC_SOCKET[] = "public"; const char JSON_KEY_LOCAL_SOCKET[] = "local"; const char JSON_KEY_POOL[] = "pool"; -QJsonObject jsonObjectForNode(Node* node) { +QJsonObject DomainServer::jsonObjectForNode(const SharedNodePointer& node) { QJsonObject nodeJson; // re-format the type name so it matches the target name @@ -402,12 +402,13 @@ QJsonObject jsonObjectForNode(Node* node) { // add the node socket information nodeJson[JSON_KEY_PUBLIC_SOCKET] = jsonForSocket(node->getPublicSocket()); nodeJson[JSON_KEY_LOCAL_SOCKET] = jsonForSocket(node->getLocalSocket()); - + // if the node has pool information, add it - if (node->getLinkedData() && !((Assignment*) node->getLinkedData())->getPool().isEmpty()) { - nodeJson[JSON_KEY_POOL] = ((Assignment*) node->getLinkedData())->getPool(); + SharedAssignmentPointer matchingAssignment = _staticAssignmentHash.value(node->getUUID()); + if (matchingAssignment) { + nodeJson[JSON_KEY_POOL] = matchingAssignment->getPool(); } - + return nodeJson; } @@ -427,10 +428,10 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QString& // enumerate the NodeList to find the assigned nodes foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { - if (node->getLinkedData()) { + if (_staticAssignmentHash.value(node->getUUID())) { // add the node using the UUID as the key QString uuidString = uuidStringWithoutCurlyBraces(node->getUUID()); - assignedNodesJSON[uuidString] = jsonObjectForNode(node.data()); + assignedNodesJSON[uuidString] = jsonObjectForNode(node); } } @@ -473,7 +474,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QString& foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { // add the node using the UUID as the key QString uuidString = uuidStringWithoutCurlyBraces(node->getUUID()); - nodesJSON[uuidString] = jsonObjectForNode(node.data()); + nodesJSON[uuidString] = jsonObjectForNode(node); } rootJSON["nodes"] = nodesJSON; diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 580a758df8..0646653d02 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -48,6 +48,9 @@ private: void removeMatchingAssignmentFromQueue(const SharedAssignmentPointer& removableAssignment); void refreshStaticAssignmentAndAddToQueue(SharedAssignmentPointer& assignment); + QJsonObject jsonForSocket(const HifiSockAddr& socket); + QJsonObject jsonObjectForNode(const SharedNodePointer& node); + HTTPManager _HTTPManager; QHash _staticAssignmentHash; From cf05600d73b0113195d9e1ff4e2d789138296c01 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 7 Feb 2014 15:27:44 -0800 Subject: [PATCH 39/42] fix miss of pingType in timePingReply, closes #1934 --- libraries/shared/src/NodeList.cpp | 62 +++++++++++++++---------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 2e78537734..2672f3b27b 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -184,39 +184,37 @@ void NodeList::setDomainHostname(const QString& domainHostname) { } void NodeList::timePingReply(const QByteArray& packet, const SharedNodePointer& sendingNode) { + QDataStream packetStream(packet); + packetStream.skipRawData(numBytesForPacketHeader(packet)); - if (sendingNode) { - QDataStream packetStream(packet); - packetStream.skipRawData(numBytesForPacketHeader(packet)); - - quint64 ourOriginalTime, othersReplyTime; - - packetStream >> ourOriginalTime >> othersReplyTime; - - quint64 now = usecTimestampNow(); - int pingTime = now - ourOriginalTime; - int oneWayFlightTime = pingTime / 2; // half of the ping is our one way flight - - // The other node's expected time should be our original time plus the one way flight time - // anything other than that is clock skew - quint64 othersExprectedReply = ourOriginalTime + oneWayFlightTime; - int clockSkew = othersReplyTime - othersExprectedReply; - - sendingNode->setPingMs(pingTime / 1000); - sendingNode->setClockSkewUsec(clockSkew); - - const bool wantDebug = false; - - if (wantDebug) { - qDebug() << "PING_REPLY from node " << *sendingNode << "\n" << - " now: " << now << "\n" << - " ourTime: " << ourOriginalTime << "\n" << - " pingTime: " << pingTime << "\n" << - " oneWayFlightTime: " << oneWayFlightTime << "\n" << - " othersReplyTime: " << othersReplyTime << "\n" << - " othersExprectedReply: " << othersExprectedReply << "\n" << - " clockSkew: " << clockSkew; - } + quint8 pingType; + quint64 ourOriginalTime, othersReplyTime; + + packetStream >> pingType >> ourOriginalTime >> othersReplyTime; + + quint64 now = usecTimestampNow(); + int pingTime = now - ourOriginalTime; + int oneWayFlightTime = pingTime / 2; // half of the ping is our one way flight + + // The other node's expected time should be our original time plus the one way flight time + // anything other than that is clock skew + quint64 othersExprectedReply = ourOriginalTime + oneWayFlightTime; + int clockSkew = othersReplyTime - othersExprectedReply; + + sendingNode->setPingMs(pingTime / 1000); + sendingNode->setClockSkewUsec(clockSkew); + + const bool wantDebug = false; + + if (wantDebug) { + qDebug() << "PING_REPLY from node " << *sendingNode << "\n" << + " now: " << now << "\n" << + " ourTime: " << ourOriginalTime << "\n" << + " pingTime: " << pingTime << "\n" << + " oneWayFlightTime: " << oneWayFlightTime << "\n" << + " othersReplyTime: " << othersReplyTime << "\n" << + " othersExprectedReply: " << othersExprectedReply << "\n" << + " clockSkew: " << clockSkew; } } From 3894fc0cb83202c2b9d1bf4cc9eb291b930c1a20 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 7 Feb 2014 17:44:43 -0800 Subject: [PATCH 40/42] Minor comment change. --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 39e1868dd0..3f32c6be09 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -448,7 +448,7 @@ void Application::paintGL() { _myCamera.setTargetRotation(_myAvatar->getHead().getOrientation()); } else if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) { - _myCamera.setTightness(0.0f); // In first person, camera follows head exactly without delay + _myCamera.setTightness(0.0f); // In first person, camera follows (untweaked) head exactly without delay _myCamera.setTargetPosition(_myAvatar->getHead().calculateAverageEyePosition()); _myCamera.setTargetRotation(_myAvatar->getHead().getCameraOrientation()); From 8c3ba5b2de4928662a8a935976bd257cf39f80bc Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 7 Feb 2014 17:45:25 -0800 Subject: [PATCH 41/42] Cruft removal. We don't use Head::YawRate stuff. --- interface/src/avatar/Avatar.h | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index c9b0bcacc2..dfe72fdc18 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -82,7 +82,6 @@ public: //getters bool isInitialized() const { return _initialized; } SkeletonModel& getSkeletonModel() { return _skeletonModel; } - float getHeadYawRate() const { return _head.yawRate; } glm::vec3 getChestPosition() const; float getScale() const { return _scale; } const glm::vec3& getVelocity() const { return _velocity; } From 6b2c7c556d5e3beb5f17eb36fe0df3fc6e564a2d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 7 Feb 2014 17:46:14 -0800 Subject: [PATCH 42/42] Fixing mouselook. Faceshift head rotations are stored separately and then integrated into the final (rendered) head rotation at the right times but do not affect the camera. --- interface/src/avatar/FaceModel.cpp | 6 +++--- interface/src/avatar/Head.cpp | 23 +++++++++++++++++++++-- interface/src/avatar/Head.h | 19 ++++++++++++++++--- interface/src/avatar/MyAvatar.cpp | 6 +++--- 4 files changed, 43 insertions(+), 11 deletions(-) diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp index d164d5c899..b9803c17cd 100644 --- a/interface/src/avatar/FaceModel.cpp +++ b/interface/src/avatar/FaceModel.cpp @@ -59,15 +59,15 @@ void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBX glm::mat3 inverse = glm::mat3(glm::inverse(parentState.transform * glm::translate(state.translation) * joint.preTransform * glm::mat4_cast(joint.preRotation))); state.rotation = glm::angleAxis(-_owningHead->getRoll(), glm::normalize(inverse * axes[2])) * - glm::angleAxis(_owningHead->getYaw(), glm::normalize(inverse * axes[1])) * - glm::angleAxis(-_owningHead->getPitch(), glm::normalize(inverse * axes[0])) * joint.rotation; + glm::angleAxis(_owningHead->getTweakedYaw(), glm::normalize(inverse * axes[1])) * + glm::angleAxis(-_owningHead->getTweakedPitch(), glm::normalize(inverse * axes[0])) * joint.rotation; } void FaceModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) { // likewise with the eye joints glm::mat4 inverse = glm::inverse(parentState.transform * glm::translate(state.translation) * joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation)); - glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getOrientation() * IDENTITY_FRONT, 0.0f)); + glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getTweakedOrientation() * IDENTITY_FRONT, 0.0f)); glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getLookAtPosition() + _owningHead->getSaccade() - _translation, 1.0f)); glm::quat between = rotationBetween(front, lookAt); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index f8faed56ed..e5d4724bb5 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -18,7 +18,6 @@ using namespace std; Head::Head(Avatar* owningAvatar) : HeadData((AvatarData*)owningAvatar), - yawRate(0.0f), _returnHeadToCenter(false), _position(0.0f, 0.0f, 0.0f), _rotation(0.0f, 0.0f, 0.0f), @@ -37,6 +36,9 @@ Head::Head(Avatar* owningAvatar) : _leftEyeBlinkVelocity(0.0f), _rightEyeBlinkVelocity(0.0f), _timeWithoutTalking(0.0f), + _tweakedPitch(0.f), + _tweakedYaw(0.f), + _tweakedRoll(0.f), _isCameraMoving(false), _faceModel(this) { @@ -186,9 +188,14 @@ glm::quat Head::getOrientation() const { return glm::quat(glm::radians(_bodyRotation)) * glm::quat(glm::radians(glm::vec3(_pitch, _yaw, _roll))); } +glm::quat Head::getTweakedOrientation() const { + return glm::quat(glm::radians(_bodyRotation)) * glm::quat(glm::radians(glm::vec3(getTweakedPitch(), getTweakedYaw(), getTweakedRoll() ))); +} + glm::quat Head::getCameraOrientation () const { Avatar* owningAvatar = static_cast(_owningAvatar); - return owningAvatar->getWorldAlignedOrientation(); + return owningAvatar->getWorldAlignedOrientation() + * glm::quat(glm::radians(glm::vec3(_pitch, 0.f, 0.0f))); } glm::quat Head::getEyeRotation(const glm::vec3& eyePosition) const { @@ -200,6 +207,18 @@ glm::vec3 Head::getScalePivot() const { return _faceModel.isActive() ? _faceModel.getTranslation() : _position; } +float Head::getTweakedYaw() const { + return glm::clamp(_yaw + _tweakedYaw, MIN_HEAD_YAW, MAX_HEAD_YAW); +} + +float Head::getTweakedPitch() const { + return glm::clamp(_pitch + _tweakedPitch, MIN_HEAD_PITCH, MAX_HEAD_PITCH); +} + +float Head::getTweakedRoll() const { + return glm::clamp(_roll + _tweakedRoll, MIN_HEAD_ROLL, MAX_HEAD_ROLL); +} + void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition) { Application::getInstance()->getGlowEffect()->begin(); diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 169f2af749..19f9efd8e6 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -13,7 +13,7 @@ #include -#include +#include #include @@ -47,6 +47,7 @@ public: void setRenderLookatVectors(bool onOff) { _renderLookatVectors = onOff; } glm::quat getOrientation() const; + glm::quat getTweakedOrientation() const; glm::quat getCameraOrientation () const; const glm::vec3& getAngularVelocity() const { return _angularVelocity; } void setAngularVelocity(glm::vec3 angularVelocity) { _angularVelocity = angularVelocity; } @@ -70,9 +71,15 @@ public: /// Returns the point about which scaling occurs. glm::vec3 getScalePivot() const; - - float yawRate; + void tweakPitch(float pitch) { _tweakedPitch = pitch; } + void tweakYaw(float yaw) { _tweakedYaw = yaw; } + void tweakRoll(float roll) { _tweakedRoll = roll; } + + float getTweakedPitch() const; + float getTweakedYaw() const; + float getTweakedRoll() const; + private: // disallow copies of the Head, copy of owning Avatar is disallowed too Head(const Head&); @@ -96,6 +103,12 @@ private: float _leftEyeBlinkVelocity; float _rightEyeBlinkVelocity; float _timeWithoutTalking; + + // tweaked angles affect the rendered head, but not the camera + float _tweakedPitch; + float _tweakedYaw; + float _tweakedRoll; + bool _isCameraMoving; FaceModel _faceModel; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 85025c1847..98eb9a4431 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -396,9 +396,9 @@ void MyAvatar::updateFromGyros(bool turnWithHead) { const float AVATAR_HEAD_PITCH_MAGNIFY = 1.0f; const float AVATAR_HEAD_YAW_MAGNIFY = 1.0f; const float AVATAR_HEAD_ROLL_MAGNIFY = 1.0f; - _head.setPitch(estimatedRotation.x * AVATAR_HEAD_PITCH_MAGNIFY); - _head.setYaw(estimatedRotation.y * AVATAR_HEAD_YAW_MAGNIFY); - _head.setRoll(estimatedRotation.z * AVATAR_HEAD_ROLL_MAGNIFY); + _head.tweakPitch(estimatedRotation.x * AVATAR_HEAD_PITCH_MAGNIFY); + _head.tweakYaw(estimatedRotation.y * AVATAR_HEAD_YAW_MAGNIFY); + _head.tweakRoll(estimatedRotation.z * AVATAR_HEAD_ROLL_MAGNIFY); // Update torso lean distance based on accelerometer data const float TORSO_LENGTH = 0.5f;