This commit is contained in:
Andrzej Kapolka 2014-02-07 14:33:25 -08:00
commit f6ca042ffc
75 changed files with 721 additions and 518 deletions

View file

@ -835,7 +835,11 @@ void AnimationServer::readPendingDatagrams() {
int headerBytes = numBytesForPacketHeader(receivedPacket); int headerBytes = numBytesForPacketHeader(receivedPacket);
// PacketType_JURISDICTION, first byte is the node type... // PacketType_JURISDICTION, first byte is the node type...
if (receivedPacket.data()[headerBytes] == NodeType::VoxelServer && ::jurisdictionListener) { if (receivedPacket.data()[headerBytes] == NodeType::VoxelServer && ::jurisdictionListener) {
::jurisdictionListener->queueReceivedPacket(nodeSockAddr, receivedPacket);
SharedNodePointer matchedNode = NodeList::getInstance()->sendingNodeForPacket(receivedPacket);
if (matchedNode) {
::jurisdictionListener->queueReceivedPacket(matchedNode, receivedPacket);
}
} }
} }
NodeList::getInstance()->processNodeData(nodeSockAddr, receivedPacket); NodeList::getInstance()->processNodeData(nodeSockAddr, receivedPacket);

View file

@ -35,17 +35,24 @@ void Agent::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr&
PacketType datagramPacketType = packetTypeForPacket(dataByteArray); PacketType datagramPacketType = packetTypeForPacket(dataByteArray);
if (datagramPacketType == PacketTypeJurisdiction) { if (datagramPacketType == PacketTypeJurisdiction) {
int headerBytes = numBytesForPacketHeader(dataByteArray); int headerBytes = numBytesForPacketHeader(dataByteArray);
// PacketType_JURISDICTION, first byte is the node type...
switch (dataByteArray[headerBytes]) { QUuid nodeUUID;
case NodeType::VoxelServer: SharedNodePointer matchedNode = NodeList::getInstance()->nodeWithUUID(nodeUUID);
_scriptEngine.getVoxelsScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(senderSockAddr,
dataByteArray); if (matchedNode) {
break; // PacketType_JURISDICTION, first byte is the node type...
case NodeType::ParticleServer: switch (dataByteArray[headerBytes]) {
_scriptEngine.getParticlesScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(senderSockAddr, case NodeType::VoxelServer:
dataByteArray); _scriptEngine.getVoxelsScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(matchedNode,
break; dataByteArray);
break;
case NodeType::ParticleServer:
_scriptEngine.getParticlesScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(matchedNode,
dataByteArray);
break;
}
} }
} else if (datagramPacketType == PacketTypeParticleAddResponse) { } else if (datagramPacketType == PacketTypeParticleAddResponse) {
// this will keep creatorTokenIDs to IDs mapped correctly // this will keep creatorTokenIDs to IDs mapped correctly
Particle::handleAddParticleResponse(dataByteArray); Particle::handleAddParticleResponse(dataByteArray);

View file

@ -131,7 +131,7 @@ void AssignmentClient::readPendingDatagrams() {
// switch our nodelist domain IP and port to whoever sent us the assignment // switch our nodelist domain IP and port to whoever sent us the assignment
nodeList->setDomainSockAddr(senderSockAddr); nodeList->setDomainSockAddr(senderSockAddr);
nodeList->setOwnerUUID(_currentAssignment->getUUID()); nodeList->setSessionUUID(_currentAssignment->getUUID());
qDebug() << "Destination IP for assignment is" << nodeList->getDomainIP().toString(); qDebug() << "Destination IP for assignment is" << nodeList->getDomainIP().toString();

View file

@ -213,12 +213,10 @@ void AudioMixer::processDatagram(const QByteArray& dataByteArray, const HifiSock
if (mixerPacketType == PacketTypeMicrophoneAudioNoEcho if (mixerPacketType == PacketTypeMicrophoneAudioNoEcho
|| mixerPacketType == PacketTypeMicrophoneAudioWithEcho || mixerPacketType == PacketTypeMicrophoneAudioWithEcho
|| mixerPacketType == PacketTypeInjectAudio) { || mixerPacketType == PacketTypeInjectAudio) {
QUuid nodeUUID;
deconstructPacketHeader(dataByteArray, nodeUUID);
NodeList* nodeList = NodeList::getInstance(); NodeList* nodeList = NodeList::getInstance();
SharedNodePointer matchingNode = nodeList->nodeWithUUID(nodeUUID); SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(dataByteArray);
if (matchingNode) { if (matchingNode) {
nodeList->updateNodeWithData(matchingNode.data(), senderSockAddr, dataByteArray); nodeList->updateNodeWithData(matchingNode.data(), senderSockAddr, dataByteArray);
@ -279,9 +277,7 @@ void AudioMixer::run() {
prepareMixForListeningNode(node.data()); prepareMixForListeningNode(node.data());
memcpy(clientPacket + numBytesPacketHeader, _clientSamples, sizeof(_clientSamples)); memcpy(clientPacket + numBytesPacketHeader, _clientSamples, sizeof(_clientSamples));
nodeList->getNodeSocket().writeDatagram((char*) clientPacket, sizeof(clientPacket), nodeList->writeDatagram((char*) clientPacket, sizeof(clientPacket), node);
node->getActiveSocket()->getAddress(),
node->getActiveSocket()->getPort());
} }
} }

View file

@ -11,6 +11,7 @@
// nodes, and broadcasts that data back to them, every BROADCAST_INTERVAL ms. // nodes, and broadcasts that data back to them, every BROADCAST_INTERVAL ms.
#include <QtCore/QCoreApplication> #include <QtCore/QCoreApplication>
#include <QtCore/QElapsedTimer>
#include <QtCore/QTimer> #include <QtCore/QTimer>
#include <Logging.h> #include <Logging.h>
@ -19,7 +20,7 @@
#include <SharedUtil.h> #include <SharedUtil.h>
#include <UUID.h> #include <UUID.h>
#include "AvatarData.h" #include "AvatarMixerClientData.h"
#include "AvatarMixer.h" #include "AvatarMixer.h"
@ -36,7 +37,7 @@ AvatarMixer::AvatarMixer(const QByteArray& packet) :
void attachAvatarDataToNode(Node* newNode) { void attachAvatarDataToNode(Node* newNode) {
if (newNode->getLinkedData() == NULL) { if (newNode->getLinkedData() == NULL) {
newNode->setLinkedData(new AvatarData()); newNode->setLinkedData(new AvatarMixerClientData());
} }
} }
@ -52,8 +53,6 @@ void broadcastAvatarData() {
int numPacketHeaderBytes = populatePacketHeader(mixedAvatarByteArray, PacketTypeBulkAvatarData); int numPacketHeaderBytes = populatePacketHeader(mixedAvatarByteArray, PacketTypeBulkAvatarData);
int packetsSent = 0;
NodeList* nodeList = NodeList::getInstance(); NodeList* nodeList = NodeList::getInstance();
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
@ -70,15 +69,11 @@ void broadcastAvatarData() {
QByteArray avatarByteArray; QByteArray avatarByteArray;
avatarByteArray.append(otherNode->getUUID().toRfc4122()); avatarByteArray.append(otherNode->getUUID().toRfc4122());
AvatarData* nodeData = (AvatarData*) otherNode->getLinkedData(); AvatarMixerClientData* nodeData = reinterpret_cast<AvatarMixerClientData*>(otherNode->getLinkedData());
avatarByteArray.append(nodeData->toByteArray()); avatarByteArray.append(nodeData->toByteArray());
if (avatarByteArray.size() + mixedAvatarByteArray.size() > MAX_PACKET_SIZE) { if (avatarByteArray.size() + mixedAvatarByteArray.size() > MAX_PACKET_SIZE) {
packetsSent++; nodeList->writeDatagram(mixedAvatarByteArray, node);
//printf("packetsSent=%d packetLength=%d\n", packetsSent, packetLength);
nodeList->getNodeSocket().writeDatagram(mixedAvatarByteArray,
node->getActiveSocket()->getAddress(),
node->getActiveSocket()->getPort());
// reset the packet // reset the packet
mixedAvatarByteArray.resize(numPacketHeaderBytes); mixedAvatarByteArray.resize(numPacketHeaderBytes);
@ -89,15 +84,45 @@ void broadcastAvatarData() {
} }
} }
packetsSent++; nodeList->writeDatagram(mixedAvatarByteArray, node);
//printf("packetsSent=%d packetLength=%d\n", packetsSent, packetLength);
nodeList->getNodeSocket().writeDatagram(mixedAvatarByteArray,
node->getActiveSocket()->getAddress(),
node->getActiveSocket()->getPort());
} }
} }
} }
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) {
AvatarMixerClientData* nodeData = reinterpret_cast<AvatarMixerClientData*>(node->getLinkedData());
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
nodeList->broadcastToNodes(avatarIdentityPacket, NodeSet() << NodeType::Agent);
avatarIdentityPacket.resize(numPacketHeaderBytes);
}
// 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->setHasSentIdentityBetweenKeyFrames(false);
}
}
// send out the final packet
if (avatarIdentityPacket.size() > numPacketHeaderBytes) {
nodeList->broadcastToNodes(avatarIdentityPacket, NodeSet() << NodeType::Agent);
}
}
void AvatarMixer::nodeKilled(SharedNodePointer killedNode) { void AvatarMixer::nodeKilled(SharedNodePointer killedNode) {
if (killedNode->getType() == NodeType::Agent if (killedNode->getType() == NodeType::Agent
&& killedNode->getLinkedData()) { && killedNode->getLinkedData()) {
@ -117,11 +142,9 @@ void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSoc
switch (packetTypeForPacket(dataByteArray)) { switch (packetTypeForPacket(dataByteArray)) {
case PacketTypeAvatarData: { case PacketTypeAvatarData: {
QUuid nodeUUID;
deconstructPacketHeader(dataByteArray, nodeUUID);
// add or update the node in our list // add or update the node in our list
SharedNodePointer avatarNode = nodeList->nodeWithUUID(nodeUUID); SharedNodePointer avatarNode = nodeList->sendingNodeForPacket(dataByteArray);
if (avatarNode) { if (avatarNode) {
// parse positional data from an node // parse positional data from an node
@ -130,6 +153,28 @@ void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSoc
} }
break; 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<AvatarMixerClientData*>(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);
}
}
}
case PacketTypeKillAvatar: { case PacketTypeKillAvatar: {
nodeList->processKillNode(dataByteArray); nodeList->processKillNode(dataByteArray);
break; break;
@ -142,6 +187,8 @@ void AvatarMixer::processDatagram(const QByteArray& dataByteArray, const HifiSoc
} }
const qint64 AVATAR_IDENTITY_KEYFRAME_MSECS = 5000;
void AvatarMixer::run() { void AvatarMixer::run() {
commonInit(AVATAR_MIXER_LOGGING_NAME, NodeType::AvatarMixer); commonInit(AVATAR_MIXER_LOGGING_NAME, NodeType::AvatarMixer);
@ -155,6 +202,9 @@ void AvatarMixer::run() {
gettimeofday(&startTime, NULL); gettimeofday(&startTime, NULL);
QElapsedTimer identityTimer;
identityTimer.start();
while (!_isFinished) { while (!_isFinished) {
QCoreApplication::processEvents(); QCoreApplication::processEvents();
@ -165,6 +215,14 @@ void AvatarMixer::run() {
broadcastAvatarData(); 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(); int usecToSleep = usecTimestamp(&startTime) + (++nextFrame * AVATAR_DATA_SEND_INTERVAL_USECS) - usecTimestampNow();
if (usecToSleep > 0) { if (usecToSleep > 0) {

View file

@ -20,6 +20,7 @@ public slots:
/// runs the avatar mixer /// runs the avatar mixer
void run(); void run();
void nodeAdded(SharedNodePointer nodeAdded);
void nodeKilled(SharedNodePointer killedNode); void nodeKilled(SharedNodePointer killedNode);
void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr); void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr);

View file

@ -0,0 +1,15 @@
//
// AvatarMixerClientData.cpp
// hifi
//
// Created by Stephen Birarda on 2/4/2014.
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
//
#include "AvatarMixerClientData.h"
AvatarMixerClientData::AvatarMixerClientData() :
_hasSentIdentityBetweenKeyFrames(false)
{
}

View file

@ -0,0 +1,29 @@
//
// 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 <QtCore/QUrl>
#include <AvatarData.h>
class AvatarMixerClientData : public AvatarData {
Q_OBJECT
public:
AvatarMixerClientData();
bool hasSentIdentityBetweenKeyFrames() const { return _hasSentIdentityBetweenKeyFrames; }
void setHasSentIdentityBetweenKeyFrames(bool hasSentIdentityBetweenKeyFrames)
{ _hasSentIdentityBetweenKeyFrames = hasSentIdentityBetweenKeyFrames; }
private:
bool _hasSentIdentityBetweenKeyFrames;
};
#endif /* defined(__hifi__AvatarMixerClientData__) */

View file

@ -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(); bool debugProcessPacket = _myServer->wantsVerboseDebug();
@ -55,8 +55,6 @@ void OctreeInboundPacketProcessor::processPacket(const HifiSockAddr& senderSockA
if (_myServer->getOctree()->handlesEditPacketType(packetType)) { if (_myServer->getOctree()->handlesEditPacketType(packetType)) {
PerformanceWarning warn(debugProcessPacket, "processPacket KNOWN TYPE",debugProcessPacket); PerformanceWarning warn(debugProcessPacket, "processPacket KNOWN TYPE",debugProcessPacket);
_receivedPacketCount++; _receivedPacketCount++;
SharedNodePointer senderNode = NodeList::getInstance()->nodeWithAddress(senderSockAddr);
const unsigned char* packetData = reinterpret_cast<const unsigned char*>(packet.data()); const unsigned char* packetData = reinterpret_cast<const unsigned char*>(packet.data());
@ -90,7 +88,7 @@ void OctreeInboundPacketProcessor::processPacket(const HifiSockAddr& senderSockA
int editDataBytesRead = _myServer->getOctree()->processEditPacketData(packetType, int editDataBytesRead = _myServer->getOctree()->processEditPacketData(packetType,
reinterpret_cast<const unsigned char*>(packet.data()), reinterpret_cast<const unsigned char*>(packet.data()),
packet.size(), packet.size(),
editData, maxSize, senderNode.data()); editData, maxSize, sendingNode);
_myServer->getOctree()->unlock(); _myServer->getOctree()->unlock();
quint64 endProcess = usecTimestampNow(); 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. // Make sure our Node and NodeList knows we've heard from this node.
QUuid& nodeUUID = DEFAULT_NODE_ID_REF; QUuid& nodeUUID = DEFAULT_NODE_ID_REF;
if (senderNode) { if (sendingNode) {
senderNode->setLastHeardMicrostamp(usecTimestampNow()); sendingNode->setLastHeardMicrostamp(usecTimestampNow());
nodeUUID = senderNode->getUUID(); nodeUUID = sendingNode->getUUID();
if (debugProcessPacket) { if (debugProcessPacket) {
qDebug() << "sender has uuid=" << nodeUUID; qDebug() << "sender has uuid=" << nodeUUID;
} }

View file

@ -63,7 +63,7 @@ public:
NodeToSenderStatsMap& getSingleSenderStats() { return _singleSenderStats; } NodeToSenderStatsMap& getSingleSenderStats() { return _singleSenderStats; }
protected: protected:
virtual void processPacket(const HifiSockAddr& senderSockAddr, const QByteArray& packet); virtual void processPacket(const SharedNodePointer& sendingNode, const QByteArray& packet);
private: private:
void trackInboundPackets(const QUuid& nodeUUID, int sequence, quint64 transitTime, void trackInboundPackets(const QUuid& nodeUUID, int sequence, quint64 transitTime,

View file

@ -48,7 +48,7 @@ bool OctreeSendThread::process() {
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) { if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
printf("nodeData->updateCurrentViewFrustum() changed=%s\n", debug::valueOf(viewFrustumChanged)); 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. 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::_totalWastedBytes = 0;
quint64 OctreeSendThread::_totalPackets = 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(); bool debug = _myServer->wantsDebugSending();
quint64 now = usecTimestampNow(); quint64 now = usecTimestampNow();
@ -142,15 +142,11 @@ int OctreeSendThread::handlePacketSend(Node* node, OctreeQueryNode* nodeData, in
} }
// actually send it // actually send it
NodeList::getInstance()->getNodeSocket().writeDatagram((char*) statsMessage, statsMessageLength, NodeList::getInstance()->writeDatagram((char*) statsMessage, statsMessageLength, SharedNodePointer(node));
nodeAddress->getAddress(),
nodeAddress->getPort());
packetSent = true; packetSent = true;
} else { } else {
// not enough room in the packet, send two packets // not enough room in the packet, send two packets
NodeList::getInstance()->getNodeSocket().writeDatagram((char*) statsMessage, statsMessageLength, NodeList::getInstance()->writeDatagram((char*) statsMessage, statsMessageLength, SharedNodePointer(node));
nodeAddress->getAddress(),
nodeAddress->getPort());
// since a stats message is only included on end of scene, don't consider any of these bytes "wasted", since // 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. // there was nothing else to send.
@ -168,9 +164,8 @@ int OctreeSendThread::handlePacketSend(Node* node, OctreeQueryNode* nodeData, in
truePacketsSent++; truePacketsSent++;
packetsSent++; packetsSent++;
NodeList::getInstance()->getNodeSocket().writeDatagram((char*) nodeData->getPacket(), nodeData->getPacketLength(), NodeList::getInstance()->writeDatagram((char*) nodeData->getPacket(), nodeData->getPacketLength(),
nodeAddress->getAddress(), SharedNodePointer(node));
nodeAddress->getPort());
packetSent = true; 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 there's actually a packet waiting, then send it.
if (nodeData->isPacketWaiting()) { if (nodeData->isPacketWaiting()) {
// just send the voxel packet // just send the voxel packet
NodeList::getInstance()->getNodeSocket().writeDatagram((char*) nodeData->getPacket(), nodeData->getPacketLength(), NodeList::getInstance()->writeDatagram((char*) nodeData->getPacket(), nodeData->getPacketLength(),
nodeAddress->getAddress(), SharedNodePointer(node));
nodeAddress->getPort());
packetSent = true; packetSent = true;
int thisWastedBytes = MAX_PACKET_SIZE - nodeData->getPacketLength(); int thisWastedBytes = MAX_PACKET_SIZE - nodeData->getPacketLength();
@ -218,7 +212,7 @@ int OctreeSendThread::handlePacketSend(Node* node, OctreeQueryNode* nodeData, in
} }
/// Version of voxel distributor that sends the deepest LOD level at once /// 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; bool forceDebugging = false;
int truePacketsSent = 0; int truePacketsSent = 0;

View file

@ -36,8 +36,8 @@ private:
QUuid _nodeUUID; QUuid _nodeUUID;
OctreeServer* _myServer; OctreeServer* _myServer;
int handlePacketSend(Node* node, OctreeQueryNode* nodeData, int& trueBytesSent, int& truePacketsSent); int handlePacketSend(const SharedNodePointer& node, OctreeQueryNode* nodeData, int& trueBytesSent, int& truePacketsSent);
int packetDistributor(Node* node, OctreeQueryNode* nodeData, bool viewFrustumChanged); int packetDistributor(const SharedNodePointer& node, OctreeQueryNode* nodeData, bool viewFrustumChanged);
OctreePacketData _packetData; OctreePacketData _packetData;
}; };

View file

@ -462,6 +462,8 @@ void OctreeServer::processDatagram(const QByteArray& dataByteArray, const HifiSo
NodeList* nodeList = NodeList::getInstance(); NodeList* nodeList = NodeList::getInstance();
PacketType packetType = packetTypeForPacket(dataByteArray); PacketType packetType = packetTypeForPacket(dataByteArray);
SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(dataByteArray);
if (packetType == getMyQueryMessageType()) { if (packetType == getMyQueryMessageType()) {
bool debug = false; bool debug = false;
@ -471,27 +473,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 // 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. // need to make sure we have it in our nodeList.
QUuid nodeUUID;
deconstructPacketHeader(dataByteArray, nodeUUID);
SharedNodePointer node = nodeList->nodeWithUUID(nodeUUID);
if (node) { if (matchingNode) {
nodeList->updateNodeWithData(node.data(), senderSockAddr, dataByteArray); nodeList->updateNodeWithData(matchingNode.data(), senderSockAddr, dataByteArray);
if (!node->getActiveSocket()) { if (!matchingNode->getActiveSocket()) {
// we don't have an active socket for this node, but they're talking to us // 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 // 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()) { if (nodeData && !nodeData->isOctreeSendThreadInitalized()) {
nodeData->initializeOctreeSendThread(this, nodeUUID); nodeData->initializeOctreeSendThread(this, matchingNode->getUUID());
} }
} }
} else if (packetType == PacketTypeJurisdictionRequest) { } else if (packetType == PacketTypeJurisdictionRequest) {
_jurisdictionSender->queueReceivedPacket(senderSockAddr, dataByteArray); _jurisdictionSender->queueReceivedPacket(matchingNode, dataByteArray);
} else if (_octreeInboundPacketProcessor && getOctree()->handlesEditPacketType(packetType)) { } else if (_octreeInboundPacketProcessor && getOctree()->handlesEditPacketType(packetType)) {
_octreeInboundPacketProcessor->queueReceivedPacket(senderSockAddr, dataByteArray); _octreeInboundPacketProcessor->queueReceivedPacket(matchingNode, dataByteArray);
} else { } else {
// let processNodeData handle it. // let processNodeData handle it.
NodeList::getInstance()->processNodeData(senderSockAddr, dataByteArray); NodeList::getInstance()->processNodeData(senderSockAddr, dataByteArray);

View file

@ -58,8 +58,8 @@ public:
// subclass may implement these method // subclass may implement these method
virtual void beforeRun() { }; virtual void beforeRun() { };
virtual bool hasSpecialPacketToSend(Node* node) { return false; } virtual bool hasSpecialPacketToSend(const SharedNodePointer& node) { return false; }
virtual int sendSpecialPacket(Node* node) { return 0; } virtual int sendSpecialPacket(const SharedNodePointer& node) { return 0; }
static void attachQueryNodeToNode(Node* newNode); static void attachQueryNodeToNode(Node* newNode);

View file

@ -43,7 +43,7 @@ void ParticleServer::beforeRun() {
pruneDeletedParticlesTimer->start(PRUNE_DELETED_PARTICLES_INTERVAL_MSECS); 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 outputBuffer[MAX_PACKET_SIZE];
unsigned char* copyAt = outputBuffer; unsigned char* copyAt = outputBuffer;
@ -63,14 +63,12 @@ void ParticleServer::particleCreated(const Particle& newParticle, Node* node) {
copyAt += sizeof(particleID); copyAt += sizeof(particleID);
packetLength += sizeof(particleID); packetLength += sizeof(particleID);
NodeList::getInstance()->getNodeSocket().writeDatagram((char*) outputBuffer, packetLength, NodeList::getInstance()->writeDatagram((char*) outputBuffer, packetLength, senderNode);
node->getActiveSocket()->getAddress(),
node->getActiveSocket()->getPort());
} }
// ParticleServer will use the "special packets" to send list of recently deleted particles // 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; bool shouldSendDeletedParticles = false;
// check to see if any new particles have been added since we last sent to this node... // check to see if any new particles have been added since we last sent to this node...
@ -85,7 +83,7 @@ bool ParticleServer::hasSpecialPacketToSend(Node* node) {
return shouldSendDeletedParticles; return shouldSendDeletedParticles;
} }
int ParticleServer::sendSpecialPacket(Node* node) { int ParticleServer::sendSpecialPacket(const SharedNodePointer& node) {
unsigned char outputBuffer[MAX_PACKET_SIZE]; unsigned char outputBuffer[MAX_PACKET_SIZE];
size_t packetLength = 0; size_t packetLength = 0;
@ -104,9 +102,7 @@ int ParticleServer::sendSpecialPacket(Node* node) {
//qDebug() << "sending PacketType_PARTICLE_ERASE packetLength:" << packetLength; //qDebug() << "sending PacketType_PARTICLE_ERASE packetLength:" << packetLength;
NodeList::getInstance()->getNodeSocket().writeDatagram((char*) outputBuffer, packetLength, NodeList::getInstance()->writeDatagram((char*) outputBuffer, packetLength, SharedNodePointer(node));
node->getActiveSocket()->getAddress(),
node->getActiveSocket()->getPort());
} }
nodeData->setLastDeletedParticlesSentAt(deletePacketSentAt); nodeData->setLastDeletedParticlesSentAt(deletePacketSentAt);

View file

@ -34,10 +34,10 @@ public:
// subclass may implement these method // subclass may implement these method
virtual void beforeRun(); virtual void beforeRun();
virtual bool hasSpecialPacketToSend(Node* node); virtual bool hasSpecialPacketToSend(const SharedNodePointer& node);
virtual int sendSpecialPacket(Node* 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: public slots:
void pruneDeletedParticles(); void pruneDeletedParticles();

View file

@ -32,12 +32,12 @@ Octree* VoxelServer::createTree() {
return new VoxelTree(true); 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); bool shouldSendEnvironments = _sendEnvironments && shouldDo(ENVIRONMENT_SEND_INTERVAL_USECS, OCTREE_SEND_INTERVAL_USECS);
return shouldSendEnvironments; return shouldSendEnvironments;
} }
int VoxelServer::sendSpecialPacket(Node* node) { int VoxelServer::sendSpecialPacket(const SharedNodePointer& node) {
int numBytesPacketHeader = populatePacketHeader(reinterpret_cast<char*>(_tempOutputBuffer), PacketTypeEnvironmentData); int numBytesPacketHeader = populatePacketHeader(reinterpret_cast<char*>(_tempOutputBuffer), PacketTypeEnvironmentData);
int envPacketLength = numBytesPacketHeader; int envPacketLength = numBytesPacketHeader;
int environmentsToSend = getSendMinimalEnvironment() ? 1 : getEnvironmentDataCount(); int environmentsToSend = getSendMinimalEnvironment() ? 1 : getEnvironmentDataCount();
@ -46,9 +46,7 @@ int VoxelServer::sendSpecialPacket(Node* node) {
envPacketLength += getEnvironmentData(i)->getBroadcastData(_tempOutputBuffer + envPacketLength); envPacketLength += getEnvironmentData(i)->getBroadcastData(_tempOutputBuffer + envPacketLength);
} }
NodeList::getInstance()->getNodeSocket().writeDatagram((char*) _tempOutputBuffer, envPacketLength, NodeList::getInstance()->writeDatagram((char*) _tempOutputBuffer, envPacketLength, SharedNodePointer(node));
node->getActiveSocket()->getAddress(),
node->getActiveSocket()->getPort());
return envPacketLength; return envPacketLength;
} }

View file

@ -43,8 +43,8 @@ public:
// subclass may implement these method // subclass may implement these method
virtual void beforeRun(); virtual void beforeRun();
virtual bool hasSpecialPacketToSend(Node* node); virtual bool hasSpecialPacketToSend(const SharedNodePointer& node);
virtual int sendSpecialPacket(Node* node); virtual int sendSpecialPacket(const SharedNodePointer& node);
private: private:

View file

@ -21,6 +21,8 @@
#include <SharedUtil.h> #include <SharedUtil.h>
#include <UUID.h> #include <UUID.h>
#include "DomainServerNodeData.h"
#include "DomainServer.h" #include "DomainServer.h"
const int RESTART_HOLD_TIME_MSECS = 5 * 1000; const int RESTART_HOLD_TIME_MSECS = 5 * 1000;
@ -57,8 +59,9 @@ DomainServer::DomainServer(int argc, char* argv[]) :
populateDefaultStaticAssignmentsExcludingTypes(parsedTypes); populateDefaultStaticAssignmentsExcludingTypes(parsedTypes);
NodeList* nodeList = NodeList::createInstance(NodeType::DomainServer, domainServerPort); 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); QTimer* silentNodeTimer = new QTimer(this);
connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes())); connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes()));
@ -209,6 +212,10 @@ void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSet<Ass
} }
} }
const NodeSet STATICALLY_ASSIGNED_NODES = NodeSet() << NodeType::AudioMixer
<< NodeType::AvatarMixer << NodeType::VoxelServer << NodeType::ParticleServer
<< NodeType::MetavoxelServer;
void DomainServer::readAvailableDatagrams() { void DomainServer::readAvailableDatagrams() {
NodeList* nodeList = NodeList::getInstance(); NodeList* nodeList = NodeList::getInstance();
@ -222,7 +229,7 @@ void DomainServer::readAvailableDatagrams() {
QByteArray receivedPacket; QByteArray receivedPacket;
NodeType_t nodeType; NodeType_t nodeType;
QUuid nodeUUID;
while (nodeList->getNodeSocket().hasPendingDatagrams()) { while (nodeList->getNodeSocket().hasPendingDatagrams()) {
receivedPacket.resize(nodeList->getNodeSocket().pendingDatagramSize()); receivedPacket.resize(nodeList->getNodeSocket().pendingDatagramSize());
@ -237,7 +244,7 @@ void DomainServer::readAvailableDatagrams() {
QDataStream packetStream(receivedPacket); QDataStream packetStream(receivedPacket);
packetStream.skipRawData(numBytesForPacketHeader(receivedPacket)); packetStream.skipRawData(numBytesForPacketHeader(receivedPacket));
deconstructPacketHeader(receivedPacket, nodeUUID); QUuid nodeUUID = uuidFromPacketHeader(receivedPacket);
packetStream >> nodeType; packetStream >> nodeType;
packetStream >> nodePublicAddress >> nodeLocalAddress; packetStream >> nodePublicAddress >> nodeLocalAddress;
@ -255,18 +262,20 @@ void DomainServer::readAvailableDatagrams() {
} }
} }
const NodeSet STATICALLY_ASSIGNED_NODES = NodeSet() << NodeType::AudioMixer
<< NodeType::AvatarMixer << NodeType::VoxelServer << NodeType::ParticleServer
<< NodeType::MetavoxelServer;
SharedAssignmentPointer matchingStaticAssignment; SharedAssignmentPointer matchingStaticAssignment;
// check if this is a non-statically assigned node, a node that is assigned and checking in for the first time // check if this is a non-statically assigned node, a node that is assigned and checking in for the first time
// or a node that has already checked in and is continuing to report for duty // or a node that has already checked in and is continuing to report for duty
if (!STATICALLY_ASSIGNED_NODES.contains(nodeType) if (!STATICALLY_ASSIGNED_NODES.contains(nodeType)
|| (matchingStaticAssignment = matchingStaticAssignmentForCheckIn(nodeUUID, nodeType)) || (matchingStaticAssignment = matchingStaticAssignmentForCheckIn(nodeUUID, nodeType))
|| nodeList->getInstance()->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
nodeUUID = QUuid::createUuid();
}
SharedNodePointer checkInNode = nodeList->addOrUpdateNode(nodeUUID, SharedNodePointer checkInNode = nodeList->addOrUpdateNode(nodeUUID,
nodeType, nodeType,
nodePublicAddress, nodePublicAddress,
@ -291,16 +300,37 @@ void DomainServer::readAvailableDatagrams() {
NodeType_t* nodeTypesOfInterest = reinterpret_cast<NodeType_t*>(receivedPacket.data() NodeType_t* nodeTypesOfInterest = reinterpret_cast<NodeType_t*>(receivedPacket.data()
+ packetStream.device()->pos()); + packetStream.device()->pos());
// always send the node their own UUID back
QDataStream broadcastDataStream(&broadcastPacket, QIODevice::Append);
broadcastDataStream << checkInNode->getUUID();
DomainServerNodeData* nodeData = reinterpret_cast<DomainServerNodeData*>(checkInNode->getLinkedData());
if (numInterestTypes > 0) { if (numInterestTypes > 0) {
QDataStream broadcastDataStream(&broadcastPacket, QIODevice::Append); // if the node has any interest types, send back those nodes as well
foreach (const SharedNodePointer& otherNode, nodeList->getNodeHash()) {
// if the node has sent no types of interest, assume they want nothing but their own ID back if (otherNode->getUUID() != nodeUUID &&
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { memchr(nodeTypesOfInterest, otherNode->getType(), numInterestTypes)) {
if (node->getUUID() != nodeUUID &&
memchr(nodeTypesOfInterest, node->getType(), numInterestTypes)) {
// don't send avatar nodes to other avatars, that will come from avatar mixer // 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<DomainServerNodeData*>(otherNode->getLinkedData())
->getSessionSecretHash().insert(nodeUUID, secretUUID);
}
broadcastDataStream << secretUUID;
} }
} }
} }
@ -546,6 +576,11 @@ void DomainServer::refreshStaticAssignmentAndAddToQueue(SharedAssignmentPointer&
_staticAssignmentHash.remove(oldUUID); _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) { void DomainServer::nodeKilled(SharedNodePointer node) {
// if this node's UUID matches a static assignment we need to throw it back in the assignment queue // 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()); SharedAssignmentPointer matchedAssignment = _staticAssignmentHash.value(node->getUUID());
@ -553,6 +588,15 @@ void DomainServer::nodeKilled(SharedNodePointer node) {
if (matchedAssignment) { if (matchedAssignment) {
refreshStaticAssignmentAndAddToQueue(matchedAssignment); refreshStaticAssignmentAndAddToQueue(matchedAssignment);
} }
// cleanup the connection secrets that we set up for this node (on the other nodes)
DomainServerNodeData* nodeData = reinterpret_cast<DomainServerNodeData*>(node->getLinkedData());
foreach (const QUuid& otherNodeSessionUUID, nodeData->getSessionSecretHash().keys()) {
SharedNodePointer otherNode = NodeList::getInstance()->nodeWithUUID(otherNodeSessionUUID);
if (otherNode) {
reinterpret_cast<DomainServerNodeData*>(otherNode->getLinkedData())->getSessionSecretHash().remove(node->getUUID());
}
}
} }
SharedAssignmentPointer DomainServer::matchingStaticAssignmentForCheckIn(const QUuid& checkInUUID, NodeType_t nodeType) { SharedAssignmentPointer DomainServer::matchingStaticAssignmentForCheckIn(const QUuid& checkInUUID, NodeType_t nodeType) {

View file

@ -30,7 +30,9 @@ public:
void exit(int retCode = 0); void exit(int retCode = 0);
public slots: 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); void nodeKilled(SharedNodePointer node);
private: private:

View file

@ -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 <QtCore/QHash>
#include <NodeData.h>
class DomainServerNodeData : public NodeData {
public:
DomainServerNodeData() : _sessionSecretHash() {};
int parseData(const QByteArray& packet) { return 0; }
QHash<QUuid, QUuid>& getSessionSecretHash() { return _sessionSecretHash; }
private:
QHash<QUuid, QUuid> _sessionSecretHash;
};
#endif /* defined(__hifi__DomainServerNodeData__) */

View file

@ -200,10 +200,12 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
audioThread->start(); audioThread->start();
connect(nodeList, SIGNAL(domainChanged(const QString&)), SLOT(domainChanged(const QString&))); 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(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer)));
connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), &_voxels, SLOT(nodeAdded(SharedNodePointer))); connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), &_voxels, SLOT(nodeAdded(SharedNodePointer)));
connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), &_voxels, SLOT(nodeKilled(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 // read the ApplicationInfo.ini file for Name/Version/Domain information
QSettings applicationInfo("resources/info/ApplicationInfo.ini", QSettings::IniFormat); QSettings applicationInfo("resources/info/ApplicationInfo.ini", QSettings::IniFormat);
@ -243,6 +245,11 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes())); connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes()));
silentNodeTimer->moveToThread(_nodeThread); silentNodeTimer->moveToThread(_nodeThread);
silentNodeTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000); 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);
identityPacketTimer->start(1000);
QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation); QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
@ -1852,12 +1859,6 @@ void Application::init() {
} }
qDebug("Loaded settings"); 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 // Set up VoxelSystem after loading preferences so we can get the desired max voxel count
_voxels.setMaxVoxels(Menu::getInstance()->getMaxVoxels()); _voxels.setMaxVoxels(Menu::getInstance()->getMaxVoxels());
_voxels.setUseVoxelShader(Menu::getInstance()->isOptionChecked(MenuOption::UseVoxelShader)); _voxels.setUseVoxelShader(Menu::getInstance()->isOptionChecked(MenuOption::UseVoxelShader));
@ -2551,10 +2552,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
int packetLength = endOfVoxelQueryPacket - voxelQueryPacket; int packetLength = endOfVoxelQueryPacket - voxelQueryPacket;
// make sure we still have an active socket // make sure we still have an active socket
if (node->getActiveSocket()) { nodeList->writeDatagram(reinterpret_cast<const char*>(voxelQueryPacket), packetLength, node);
nodeList->getNodeSocket().writeDatagram((char*) voxelQueryPacket, packetLength,
node->getActiveSocket()->getAddress(), node->getActiveSocket()->getPort());
}
// Feed number of bytes to corresponding channel of the bandwidth meter // Feed number of bytes to corresponding channel of the bandwidth meter
_bandwidthMeter.outputStream(BandwidthMeter::VOXELS).updateValue(packetLength); _bandwidthMeter.outputStream(BandwidthMeter::VOXELS).updateValue(packetLength);
@ -3858,7 +3856,7 @@ void Application::updateWindowTitle(){
QString buildVersion = " (build " + applicationVersion() + ")"; QString buildVersion = " (build " + applicationVersion() + ")";
NodeList* nodeList = NodeList::getInstance(); NodeList* nodeList = NodeList::getInstance();
QString title = QString() + _profile.getUsername() + " " + nodeList->getOwnerUUID().toString() QString title = QString() + _profile.getUsername() + " " + nodeList->getSessionUUID().toString()
+ " @ " + nodeList->getDomainHostname() + buildVersion; + " @ " + nodeList->getDomainHostname() + buildVersion;
qDebug("Application title set to: %s", title.toStdString().c_str()); qDebug("Application title set to: %s", title.toStdString().c_str());
@ -3883,6 +3881,13 @@ void Application::domainChanged(const QString& domainHostname) {
_particles.clear(); _particles.clear();
} }
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) { void Application::nodeKilled(SharedNodePointer node) {
if (node->getType() == NodeType::VoxelServer) { if (node->getType() == NodeType::VoxelServer) {
QUuid nodeUUID = node->getUUID(); QUuid nodeUUID = node->getUUID();
@ -3952,27 +3957,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. // Attempt to identify the sender from it's address.
SharedNodePointer serverNode = NodeList::getInstance()->nodeWithAddress(senderSockAddr); if (sendingNode) {
if (serverNode) { QUuid nodeUUID = sendingNode->getUUID();
QUuid nodeUUID = serverNode->getUUID();
// now that we know the node ID, let's add these stats to the stats for that node... // now that we know the node ID, let's add these stats to the stats for that node...
_voxelSceneStatsLock.lockForWrite(); _voxelSceneStatsLock.lockForWrite();
if (_octreeServerSceneStats.find(nodeUUID) != _octreeServerSceneStats.end()) { if (_octreeServerSceneStats.find(nodeUUID) != _octreeServerSceneStats.end()) {
VoxelSceneStats& stats = _octreeServerSceneStats[nodeUUID]; VoxelSceneStats& stats = _octreeServerSceneStats[nodeUUID];
stats.trackIncomingOctreePacket(packet, wasStatsPacket, serverNode->getClockSkewUsec()); stats.trackIncomingOctreePacket(packet, wasStatsPacket, sendingNode->getClockSkewUsec());
} }
_voxelSceneStatsLock.unlock(); _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 // 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 // parse the incoming stats datas stick it in a temporary object for now, while we
// determine which server it belongs to // determine which server it belongs to
@ -3980,8 +3983,8 @@ int Application::parseOctreeStats(const QByteArray& packet, const HifiSockAddr&
int statsMessageLength = temp.unpackFromMessage(reinterpret_cast<const unsigned char*>(packet.data()), packet.size()); int statsMessageLength = temp.unpackFromMessage(reinterpret_cast<const unsigned char*>(packet.data()), packet.size());
// quick fix for crash... why would voxelServer be NULL? // quick fix for crash... why would voxelServer be NULL?
if (server) { if (sendingNode) {
QUuid nodeUUID = server->getUUID(); QUuid nodeUUID = sendingNode->getUUID();
// now that we know the node ID, let's add these stats to the stats for that node... // now that we know the node ID, let's add these stats to the stats for that node...
_voxelSceneStatsLock.lockForWrite(); _voxelSceneStatsLock.lockForWrite();
@ -3998,7 +4001,7 @@ int Application::parseOctreeStats(const QByteArray& packet, const HifiSockAddr&
// see if this is the first we've heard of this node... // see if this is the first we've heard of this node...
NodeToJurisdictionMap* jurisdiction = NULL; NodeToJurisdictionMap* jurisdiction = NULL;
if (server->getType() == NodeType::VoxelServer) { if (sendingNode->getType() == NodeType::VoxelServer) {
jurisdiction = &_voxelServerJurisdictions; jurisdiction = &_voxelServerJurisdictions;
} else { } else {
jurisdiction = &_particleServerJurisdictions; jurisdiction = &_particleServerJurisdictions;

View file

@ -126,8 +126,6 @@ public:
void touchEndEvent(QTouchEvent* event); void touchEndEvent(QTouchEvent* event);
void touchUpdateEvent(QTouchEvent* event); void touchUpdateEvent(QTouchEvent* event);
void updateWindowTitle();
void wheelEvent(QWheelEvent* event); void wheelEvent(QWheelEvent* event);
void makeVoxel(glm::vec3 position, void makeVoxel(glm::vec3 position,
@ -214,6 +212,8 @@ signals:
public slots: public slots:
void domainChanged(const QString& domainHostname); void domainChanged(const QString& domainHostname);
void updateWindowTitle();
void nodeAdded(SharedNodePointer node);
void nodeKilled(SharedNodePointer node); void nodeKilled(SharedNodePointer node);
void packetSent(quint64 length); void packetSent(quint64 length);
@ -472,8 +472,8 @@ private:
PieMenu _pieMenu; PieMenu _pieMenu;
int parseOctreeStats(const QByteArray& packet, const HifiSockAddr& senderAddress); int parseOctreeStats(const QByteArray& packet, const SharedNodePointer& sendingNode);
void trackIncomingVoxelPacket(const QByteArray& packet, const HifiSockAddr& senderSockAddr, bool wasStatsPacket); void trackIncomingVoxelPacket(const QByteArray& packet, const SharedNodePointer& sendingNode, bool wasStatsPacket);
NodeToJurisdictionMap _voxelServerJurisdictions; NodeToJurisdictionMap _voxelServerJurisdictions;
NodeToJurisdictionMap _particleServerJurisdictions; NodeToJurisdictionMap _particleServerJurisdictions;

View file

@ -388,7 +388,7 @@ void Audio::handleAudioInput() {
NodeList* nodeList = NodeList::getInstance(); NodeList* nodeList = NodeList::getInstance();
SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer); SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer);
if (audioMixer && nodeList->getNodeActiveSocketOrPing(audioMixer.data())) { if (audioMixer && nodeList->getNodeActiveSocketOrPing(audioMixer)) {
MyAvatar* interfaceAvatar = Application::getInstance()->getAvatar(); MyAvatar* interfaceAvatar = Application::getInstance()->getAvatar();
glm::vec3 headPosition = interfaceAvatar->getHead().getPosition(); glm::vec3 headPosition = interfaceAvatar->getHead().getPosition();
glm::quat headOrientation = interfaceAvatar->getHead().getOrientation(); glm::quat headOrientation = interfaceAvatar->getHead().getOrientation();
@ -409,10 +409,9 @@ void Audio::handleAudioInput() {
memcpy(currentPacketPtr, &headOrientation, sizeof(headOrientation)); memcpy(currentPacketPtr, &headOrientation, sizeof(headOrientation));
currentPacketPtr += sizeof(headOrientation); currentPacketPtr += sizeof(headOrientation);
nodeList->getNodeSocket().writeDatagram(monoAudioDataPacket, nodeList->writeDatagram(monoAudioDataPacket,
NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes,
audioMixer->getActiveSocket()->getAddress(), audioMixer);
audioMixer->getActiveSocket()->getPort());
Application::getInstance()->getBandwidthMeter()->outputStream(BandwidthMeter::AUDIO) Application::getInstance()->getBandwidthMeter()->outputStream(BandwidthMeter::AUDIO)
.updateValue(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes); .updateValue(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes);

View file

@ -84,31 +84,31 @@ void DatagramProcessor::processDatagrams() {
printf("got PacketType_VOXEL_DATA, sequence:%d flightTime:%d\n", sequence, flightTime); 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 SharedNodePointer matchedNode = NodeList::getInstance()->sendingNodeForPacket(incomingPacket);
application->_voxelProcessor.queueReceivedPacket(senderSockAddr, incomingPacket);
if (matchedNode) {
// add this packet to our list of voxel packets and process them on the voxel processing
application->_voxelProcessor.queueReceivedPacket(matchedNode, incomingPacket);
}
break; break;
} }
case PacketTypeMetavoxelData: case PacketTypeMetavoxelData:
application->_metavoxels.processData(incomingPacket, senderSockAddr); application->_metavoxels.processData(incomingPacket, senderSockAddr);
break; break;
case PacketTypeBulkAvatarData: case PacketTypeBulkAvatarData:
case PacketTypeKillAvatar: { case PacketTypeKillAvatar:
case PacketTypeAvatarIdentity: {
// update having heard from the avatar-mixer and record the bytes received // update having heard from the avatar-mixer and record the bytes received
SharedNodePointer avatarMixer = NodeList::getInstance()->nodeWithAddress(senderSockAddr); SharedNodePointer avatarMixer = nodeList->sendingNodeForPacket(incomingPacket);
if (avatarMixer) { if (avatarMixer) {
avatarMixer->setLastHeardMicrostamp(usecTimestampNow()); avatarMixer->setLastHeardMicrostamp(usecTimestampNow());
avatarMixer->recordBytesReceived(incomingPacket.size()); avatarMixer->recordBytesReceived(incomingPacket.size());
if (packetTypeForPacket(incomingPacket) == PacketTypeBulkAvatarData) { QMetaObject::invokeMethod(&application->getAvatarManager(), "processAvatarMixerDatagram",
QMetaObject::invokeMethod(&application->getAvatarManager(), "processAvatarMixerDatagram", Q_ARG(const QByteArray&, incomingPacket),
Q_ARG(const QByteArray&, incomingPacket), Q_ARG(const QWeakPointer<Node>&, avatarMixer));
Q_ARG(const QWeakPointer<Node>&, avatarMixer));
} else {
// this is an avatar kill, pass it to the application AvatarManager
QMetaObject::invokeMethod(&application->getAvatarManager(), "processKillAvatar",
Q_ARG(const QByteArray&, incomingPacket));
}
} }
application->_bandwidthMeter.inputStream(BandwidthMeter::AVATARS).updateValue(incomingPacket.size()); application->_bandwidthMeter.inputStream(BandwidthMeter::AVATARS).updateValue(incomingPacket.size());

View file

@ -766,12 +766,12 @@ void Menu::editPreferences() {
QFormLayout* form = new QFormLayout(); QFormLayout* form = new QFormLayout();
layout->addLayout(form, 1); layout->addLayout(form, 1);
QString faceURLString = applicationInstance->getProfile()->getFaceModelURL().toString(); QString faceURLString = applicationInstance->getAvatar()->getHead().getFaceModel().getURL().toString();
QLineEdit* faceURLEdit = new QLineEdit(faceURLString); QLineEdit* faceURLEdit = new QLineEdit(faceURLString);
faceURLEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH); faceURLEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH);
form->addRow("Face URL:", faceURLEdit); form->addRow("Face URL:", faceURLEdit);
QString skeletonURLString = applicationInstance->getProfile()->getSkeletonModelURL().toString(); QString skeletonURLString = applicationInstance->getAvatar()->getSkeletonModel().getURL().toString();
QLineEdit* skeletonURLEdit = new QLineEdit(skeletonURLString); QLineEdit* skeletonURLEdit = new QLineEdit(skeletonURLString);
skeletonURLEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH); skeletonURLEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH);
form->addRow("Skeleton URL:", skeletonURLEdit); form->addRow("Skeleton URL:", skeletonURLEdit);
@ -832,27 +832,25 @@ void Menu::editPreferences() {
int ret = dialog.exec(); int ret = dialog.exec();
if (ret == QDialog::Accepted) { if (ret == QDialog::Accepted) {
QUrl faceModelURL(faceURLEdit->text()); QUrl faceModelURL(faceURLEdit->text());
bool shouldDispatchIdentityPacket = false;
if (faceModelURL.toString() != faceURLString) { if (faceModelURL.toString() != faceURLString) {
// change the faceModelURL in the profile, it will also update this user's BlendFace // change the faceModelURL in the profile, it will also update this user's BlendFace
applicationInstance->getProfile()->setFaceModelURL(faceModelURL); applicationInstance->getAvatar()->setFaceModelURL(faceModelURL);
shouldDispatchIdentityPacket = true;
// 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());
} }
QUrl skeletonModelURL(skeletonURLEdit->text()); QUrl skeletonModelURL(skeletonURLEdit->text());
if (skeletonModelURL.toString() != skeletonURLString) { if (skeletonModelURL.toString() != skeletonURLString) {
// change the skeletonModelURL in the profile, it will also update this user's Body // change the skeletonModelURL in the profile, it will also update this user's Body
applicationInstance->getProfile()->setSkeletonModelURL(skeletonModelURL); applicationInstance->getAvatar()->setSkeletonModelURL(skeletonModelURL);
shouldDispatchIdentityPacket = true;
// send the new skeleton model URL to the data-server (if we have a client UUID) }
DataServerClient::putValueForKeyAndUserString(DataServerKey::SkeletonURL,
skeletonModelURL.toString().toLocal8Bit().constData(), if (shouldDispatchIdentityPacket) {
applicationInstance->getProfile()->getUserString()); applicationInstance->getAvatar()->sendIdentityPacket();
} }
applicationInstance->getAvatar()->getHead().setPupilDilation(pupilDilation->value() / (float)pupilDilation->maximum()); applicationInstance->getAvatar()->getHead().setPupilDilation(pupilDilation->value() / (float)pupilDilation->maximum());

View file

@ -230,10 +230,7 @@ void MetavoxelClient::receivedData(const QByteArray& data) {
void MetavoxelClient::sendData(const QByteArray& data) { void MetavoxelClient::sendData(const QByteArray& data) {
QMutexLocker locker(&_node->getMutex()); QMutexLocker locker(&_node->getMutex());
const HifiSockAddr* address = _node->getActiveSocket(); NodeList::getInstance()->writeDatagram(data, _node);
if (address) {
NodeList::getInstance()->getNodeSocket().writeDatagram(data, address->getAddress(), address->getPort());
}
} }
void MetavoxelClient::readPacket(Bitstream& in) { void MetavoxelClient::readPacket(Bitstream& in) {

View file

@ -123,7 +123,6 @@ void ParticleTreeRenderer::renderElement(OctreeElement* element, RenderArgs* arg
} }
} }
void ParticleTreeRenderer::processEraseMessage(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr, void ParticleTreeRenderer::processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) {
Node* sourceNode) { static_cast<ParticleTree*>(_tree)->processEraseMessage(dataByteArray, sourceNode);
static_cast<ParticleTree*>(_tree)->processEraseMessage(dataByteArray, senderSockAddr, sourceNode);
} }

View file

@ -38,7 +38,7 @@ public:
ParticleTree* getTree() { return (ParticleTree*)_tree; } 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 init();
virtual void render(); virtual void render();

View file

@ -14,7 +14,7 @@
#include "Menu.h" #include "Menu.h"
#include "VoxelPacketProcessor.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), PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
"VoxelPacketProcessor::processPacket()"); "VoxelPacketProcessor::processPacket()");
@ -44,7 +44,7 @@ void VoxelPacketProcessor::processPacket(const HifiSockAddr& senderSockAddr, con
// then process any remaining bytes as if it was another packet // then process any remaining bytes as if it was another packet
if (voxelPacketType == PacketTypeOctreeStats) { if (voxelPacketType == PacketTypeOctreeStats) {
int statsMessageLength = app->parseOctreeStats(mutablePacket, senderSockAddr); int statsMessageLength = app->parseOctreeStats(mutablePacket, sendingNode);
wasStatsPacket = true; wasStatsPacket = true;
if (messageLength > statsMessageLength) { if (messageLength > statsMessageLength) {
mutablePacket = mutablePacket.mid(statsMessageLength); mutablePacket = mutablePacket.mid(statsMessageLength);
@ -60,26 +60,25 @@ void VoxelPacketProcessor::processPacket(const HifiSockAddr& senderSockAddr, con
voxelPacketType = packetTypeForPacket(mutablePacket); voxelPacketType = packetTypeForPacket(mutablePacket);
if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) {
app->trackIncomingVoxelPacket(mutablePacket, senderSockAddr, wasStatsPacket); app->trackIncomingVoxelPacket(mutablePacket, sendingNode, wasStatsPacket);
SharedNodePointer serverNode = NodeList::getInstance()->nodeWithAddress(senderSockAddr); if (sendingNode) {
if (serverNode && serverNode->getActiveSocket() && *serverNode->getActiveSocket() == senderSockAddr) {
switch(voxelPacketType) { switch(voxelPacketType) {
case PacketTypeParticleErase: { case PacketTypeParticleErase: {
app->_particles.processEraseMessage(mutablePacket, senderSockAddr, serverNode.data()); app->_particles.processEraseMessage(mutablePacket, sendingNode);
} break; } break;
case PacketTypeParticleData: { case PacketTypeParticleData: {
app->_particles.processDatagram(mutablePacket, senderSockAddr, serverNode.data()); app->_particles.processDatagram(mutablePacket, sendingNode);
} break; } break;
case PacketTypeEnvironmentData: { case PacketTypeEnvironmentData: {
app->_environment.parseData(senderSockAddr, mutablePacket); app->_environment.parseData(*sendingNode->getActiveSocket(), mutablePacket);
} break; } break;
default : { default : {
app->_voxels.setDataSourceUUID(serverNode->getUUID()); app->_voxels.setDataSourceUUID(sendingNode->getUUID());
app->_voxels.parseData(mutablePacket); app->_voxels.parseData(mutablePacket);
app->_voxels.setDataSourceUUID(QUuid()); app->_voxels.setDataSourceUUID(QUuid());
} break; } break;

View file

@ -17,6 +17,6 @@
/// the user is responsible for reading inbound packets and adding them to the processing queue by calling queueReceivedPacket() /// the user is responsible for reading inbound packets and adding them to the processing queue by calling queueReceivedPacket()
class VoxelPacketProcessor : public ReceivedPacketProcessor { class VoxelPacketProcessor : public ReceivedPacketProcessor {
protected: protected:
virtual void processPacket(const HifiSockAddr& senderSockAddr, const QByteArray& packet); virtual void processPacket(const SharedNodePointer& sendingNode, const QByteArray& packet);
}; };
#endif // __shared__VoxelPacketProcessor__ #endif // __shared__VoxelPacketProcessor__

View file

@ -336,6 +336,16 @@ bool Avatar::findSphereCollision(const glm::vec3& sphereCenter, float sphereRadi
return false; return false;
} }
void Avatar::setFaceModelURL(const QUrl &faceModelURL) {
AvatarData::setFaceModelURL(faceModelURL);
_head.getFaceModel().setURL(faceModelURL);
}
void Avatar::setSkeletonModelURL(const QUrl &skeletonModelURL) {
AvatarData::setSkeletonModelURL(skeletonModelURL);
_skeletonModel.setURL(skeletonModelURL);
}
int Avatar::parseData(const QByteArray& packet) { int Avatar::parseData(const QByteArray& packet) {
// change in position implies movement // change in position implies movement
glm::vec3 oldPosition = _position; glm::vec3 oldPosition = _position;

View file

@ -112,7 +112,10 @@ public:
virtual bool findSphereCollision(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision); virtual bool findSphereCollision(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision);
virtual bool isMyAvatar() { return false; } virtual bool isMyAvatar() { return false; }
virtual void setFaceModelURL(const QUrl& faceModelURL);
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
int parseData(const QByteArray& packet); int parseData(const QByteArray& packet);
static void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2); static void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2);

View file

@ -123,47 +123,29 @@ void AvatarManager::renderAvatarFades() {
} }
} }
void AvatarManager::processDataServerResponse(const QString& userString, const QStringList& keyList, void AvatarManager::processAvatarMixerDatagram(const QByteArray& datagram, const QWeakPointer<Node>& mixerWeakPointer) {
const QStringList &valueList) { switch (packetTypeForPacket(datagram)) {
QUuid avatarKey = QUuid(userString); case PacketTypeBulkAvatarData:
if (avatarKey == MY_AVATAR_KEY) { processAvatarDataPacket(datagram, mixerWeakPointer);
// ignore updates to our own mesh break;
return; case PacketTypeAvatarIdentity:
} processAvatarIdentityPacket(datagram);
for (int i = 0; i < keyList.size(); i++) { break;
if (valueList[i] != " ") { case PacketTypeKillAvatar:
if (keyList[i] == DataServerKey::FaceMeshURL || keyList[i] == DataServerKey::SkeletonURL) { processKillAvatar(datagram);
// mesh URL for a UUID, find avatar in our list break;
AvatarSharedPointer matchingAvatar = _avatarHash.value(avatarKey); default:
if (matchingAvatar) { break;
Avatar* avatar = static_cast<Avatar*>(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<Node>& mixerWeakPointer) { void AvatarManager::processAvatarDataPacket(const QByteArray &datagram, const QWeakPointer<Node> &mixerWeakPointer) {
int bytesRead = numBytesForPacketHeader(datagram); int bytesRead = numBytesForPacketHeader(datagram);
QByteArray dummyAvatarByteArray = byteArrayWithPopluatedHeader(PacketTypeAvatarData); QByteArray dummyAvatarByteArray = byteArrayWithPopluatedHeader(PacketTypeAvatarData);
int numDummyHeaderBytes = dummyAvatarByteArray.size(); int numDummyHeaderBytes = dummyAvatarByteArray.size();
int numDummyHeaderBytesWithoutUUID = numDummyHeaderBytes - NUM_BYTES_RFC4122_UUID; int numDummyHeaderBytesWithoutUUID = numDummyHeaderBytes - NUM_BYTES_RFC4122_UUID;
// enumerate over all of the avatars in this packet // enumerate over all of the avatars in this packet
// only add them if mixerWeakPointer points to something (meaning that mixer is still around) // only add them if mixerWeakPointer points to something (meaning that mixer is still around)
while (bytesRead < datagram.size() && mixerWeakPointer.data()) { while (bytesRead < datagram.size() && mixerWeakPointer.data()) {
@ -180,10 +162,6 @@ void AvatarManager::processAvatarMixerDatagram(const QByteArray& datagram, const
matchingAvatar = AvatarSharedPointer(avatar); matchingAvatar = AvatarSharedPointer(avatar);
_avatarHash.insert(nodeUUID, matchingAvatar); _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."; qDebug() << "Adding avatar with UUID" << nodeUUID << "to AvatarManager hash.";
} }
@ -196,6 +174,35 @@ void AvatarManager::processAvatarMixerDatagram(const QByteArray& datagram, const
// have the matching (or new) avatar parse the data from the packet // have the matching (or new) avatar parse the data from the packet
bytesRead += matchingAvatar->parseData(dummyAvatarByteArray) - numDummyHeaderBytesWithoutUUID; 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()) {
QUrl faceMeshURL, skeletonURL;
identityStream >> nodeUUID >> faceMeshURL >> skeletonURL;
// mesh URL for a UUID, find avatar in our list
AvatarSharedPointer matchingAvatar = _avatarHash.value(nodeUUID);
if (matchingAvatar) {
Avatar* avatar = static_cast<Avatar*>(matchingAvatar.data());
if (avatar->getFaceModelURL() != faceMeshURL) {
avatar->setFaceModelURL(faceMeshURL);
}
if (avatar->getSkeletonModelURL() != skeletonURL) {
avatar->setSkeletonModelURL(skeletonURL);
}
}
}
} }
void AvatarManager::processKillAvatar(const QByteArray& datagram) { void AvatarManager::processKillAvatar(const QByteArray& datagram) {

View file

@ -20,7 +20,7 @@
class MyAvatar; class MyAvatar;
class AvatarManager : public QObject, public DataServerCallbackObject, public AvatarHashMap { class AvatarManager : public QObject, public AvatarHashMap {
Q_OBJECT Q_OBJECT
public: public:
AvatarManager(QObject* parent = 0); AvatarManager(QObject* parent = 0);
@ -35,13 +35,14 @@ public:
void clearOtherAvatars(); void clearOtherAvatars();
public slots: public slots:
void processDataServerResponse(const QString& userString, const QStringList& keyList, const QStringList& valueList);
void processAvatarMixerDatagram(const QByteArray& datagram, const QWeakPointer<Node>& mixerWeakPointer); void processAvatarMixerDatagram(const QByteArray& datagram, const QWeakPointer<Node>& mixerWeakPointer);
void processKillAvatar(const QByteArray& datagram);
private: private:
AvatarManager(const AvatarManager& other); AvatarManager(const AvatarManager& other);
void processAvatarDataPacket(const QByteArray& packet, const QWeakPointer<Node>& mixerWeakPointer);
void processAvatarIdentityPacket(const QByteArray& packet);
void processKillAvatar(const QByteArray& datagram);
void simulateAvatarFades(float deltaTime); void simulateAvatarFades(float deltaTime);
void renderAvatarFades(); void renderAvatarFades();

View file

@ -608,6 +608,9 @@ void MyAvatar::saveData(QSettings* settings) {
settings->setValue("leanScale", _leanScale); settings->setValue("leanScale", _leanScale);
settings->setValue("scale", _targetScale); settings->setValue("scale", _targetScale);
settings->setValue("faceModelURL", _faceModelURL);
settings->setValue("skeletonModelURL", _skeletonModelURL);
settings->endGroup(); settings->endGroup();
} }
@ -632,6 +635,9 @@ void MyAvatar::loadData(QSettings* settings) {
_targetScale = loadSetting(settings, "scale", 1.0f); _targetScale = loadSetting(settings, "scale", 1.0f);
setScale(_scale); setScale(_scale);
Application::getInstance()->getCamera()->setScale(_scale); Application::getInstance()->getCamera()->setScale(_scale);
setFaceModelURL(settings->value("faceModelURL").toUrl());
setSkeletonModelURL(settings->value("skeletonModelURL").toUrl());
settings->endGroup(); settings->endGroup();
} }
@ -641,6 +647,13 @@ void MyAvatar::sendKillAvatar() {
NodeList::getInstance()->broadcastToNodes(killPacket, NodeSet() << NodeType::AvatarMixer); NodeList::getInstance()->broadcastToNodes(killPacket, NodeSet() << NodeType::AvatarMixer);
} }
void MyAvatar::sendIdentityPacket() {
QByteArray identityPacket = byteArrayWithPopluatedHeader(PacketTypeAvatarIdentity);
identityPacket.append(AvatarData::identityByteArray());
NodeList::getInstance()->broadcastToNodes(identityPacket, NodeSet() << NodeType::AvatarMixer);
}
void MyAvatar::orbit(const glm::vec3& position, int deltaX, int deltaY) { void MyAvatar::orbit(const glm::vec3& position, int deltaX, int deltaY) {
// first orbit horizontally // first orbit horizontally
glm::quat orientation = getOrientation(); glm::quat orientation = getOrientation();

View file

@ -94,6 +94,8 @@ public slots:
void increaseSize(); void increaseSize();
void decreaseSize(); void decreaseSize();
void resetSize(); void resetSize();
void sendIdentityPacket();
private: private:
bool _mousePressed; bool _mousePressed;

View file

@ -20,17 +20,13 @@ Profile::Profile(const QString &username) :
_uuid(), _uuid(),
_lastDomain(), _lastDomain(),
_lastPosition(0.0, 0.0, 0.0), _lastPosition(0.0, 0.0, 0.0),
_lastOrientationSend(0), _lastOrientationSend(0)
_faceModelURL(),
_skeletonModelURL()
{ {
if (!username.isEmpty()) { if (!username.isEmpty()) {
setUsername(username); setUsername(username);
// we've been given a new username, ask the data-server for profile // we've been given a new username, ask the data-server for profile
DataServerClient::getValueForKeyAndUserString(DataServerKey::UUID, getUserString(), this); 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 // send our current domain server to the data-server
updateDomain(NodeList::getInstance()->getDomainHostname()); updateDomain(NodeList::getInstance()->getDomainHostname());
@ -45,34 +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::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) { void Profile::updateDomain(const QString& domain) {
if (_lastDomain != domain) { if (_lastDomain != domain) {
_lastDomain = domain; _lastDomain = domain;
@ -137,8 +105,6 @@ void Profile::saveData(QSettings* settings) {
settings->setValue("username", _username); settings->setValue("username", _username);
settings->setValue("UUID", _uuid); settings->setValue("UUID", _uuid);
settings->setValue("faceModelURL", _faceModelURL);
settings->setValue("skeletonModelURL", _skeletonModelURL);
settings->endGroup(); settings->endGroup();
} }
@ -148,8 +114,6 @@ void Profile::loadData(QSettings* settings) {
setUsername(settings->value("username").toString()); setUsername(settings->value("username").toString());
this->setUUID(settings->value("UUID").toUuid()); this->setUUID(settings->value("UUID").toUuid());
_faceModelURL = settings->value("faceModelURL").toUrl();
_skeletonModelURL = settings->value("skeletonModelURL").toUrl();
settings->endGroup(); settings->endGroup();
} }
@ -157,17 +121,7 @@ void Profile::loadData(QSettings* settings) {
void Profile::processDataServerResponse(const QString& userString, const QStringList& keyList, const QStringList& valueList) { void Profile::processDataServerResponse(const QString& userString, const QStringList& keyList, const QStringList& valueList) {
for (int i = 0; i < keyList.size(); i++) { for (int i = 0; i < keyList.size(); i++) {
if (valueList[i] != " ") { if (valueList[i] != " ") {
if (keyList[i] == DataServerKey::FaceMeshURL) { if (keyList[i] == DataServerKey::Domain && keyList[i + 1] == DataServerKey::Position &&
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 &&
keyList[i + 2] == DataServerKey::Orientation && valueList[i] != " " && keyList[i + 2] == DataServerKey::Orientation && valueList[i] != " " &&
valueList[i + 1] != " " && valueList[i + 2] != " ") { valueList[i + 1] != " " && valueList[i + 2] != " ") {

View file

@ -28,15 +28,9 @@ public:
const QString& getUsername() const { return _username; } const QString& getUsername() const { return _username; }
void setUUID(const QUuid& uuid); void setUUID(const QUuid& uuid) { _uuid = uuid; }
const QUuid& getUUID() { return _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 updateDomain(const QString& domain);
void updatePosition(const glm::vec3 position); void updatePosition(const glm::vec3 position);
void updateOrientation(const glm::quat& orientation); void updateOrientation(const glm::quat& orientation);
@ -58,8 +52,6 @@ private:
glm::vec3 _lastPosition; glm::vec3 _lastPosition;
glm::vec3 _lastOrientation; glm::vec3 _lastOrientation;
quint64 _lastOrientationSend; quint64 _lastOrientationSend;
QUrl _faceModelURL;
QUrl _skeletonModelURL;
}; };
#endif /* defined(__hifi__Profile__) */ #endif /* defined(__hifi__Profile__) */

View file

@ -265,7 +265,7 @@ void VoxelStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t serv
std::stringstream extraDetails(""); std::stringstream extraDetails("");
std::stringstream linkDetails(""); std::stringstream linkDetails("");
if (nodeList->getNodeActiveSocketOrPing(node.data())) { if (nodeList->getNodeActiveSocketOrPing(node)) {
serverDetails << "active "; serverDetails << "active ";
} else { } else {
serverDetails << "inactive "; serverDetails << "inactive ";

View file

@ -93,12 +93,8 @@ void AudioInjector::injectAudio() {
// grab our audio mixer from the NodeList, if it exists // grab our audio mixer from the NodeList, if it exists
SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer); SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer);
if (audioMixer && nodeList->getNodeActiveSocketOrPing(audioMixer.data())) { // send off this audio packet
// send off this audio packet nodeList->writeDatagram(injectAudioPacket, audioMixer);
nodeList->getNodeSocket().writeDatagram(injectAudioPacket,
audioMixer->getActiveSocket()->getAddress(),
audioMixer->getActiveSocket()->getPort());
}
currentSendPosition += bytesToCopy; currentSendPosition += bytesToCopy;

View file

@ -270,6 +270,48 @@ int AvatarData::parseData(const QByteArray& packet) {
return sourceBuffer - startPosition; return sourceBuffer - startPosition;
} }
bool AvatarData::hasIdentityChangedAfterParsing(const QByteArray &packet) {
QDataStream packetStream(packet);
packetStream.skipRawData(numBytesForPacketHeader(packet));
QUuid avatarUUID;
QUrl faceModelURL, skeletonModelURL;
packetStream >> avatarUUID >> faceModelURL >> skeletonModelURL;
bool hasIdentityChanged = false;
if (faceModelURL != _faceModelURL) {
setFaceModelURL(faceModelURL);
hasIdentityChanged = true;
}
if (skeletonModelURL != _skeletonModelURL) {
setSkeletonModelURL(skeletonModelURL);
hasIdentityChanged = true;
}
return hasIdentityChanged;
}
QByteArray AvatarData::identityByteArray() {
QByteArray identityData;
QDataStream identityStream(&identityData, QIODevice::Append);
identityStream << QUuid() << _faceModelURL << _skeletonModelURL;
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) { void AvatarData::setClampedTargetScale(float targetScale) {
targetScale = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); targetScale = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE);

View file

@ -30,6 +30,7 @@ typedef unsigned long long quint64;
#include <glm/gtc/quaternion.hpp> #include <glm/gtc/quaternion.hpp>
#include <QtCore/QObject> #include <QtCore/QObject>
#include <QtCore/QUrl>
#include <QtCore/QUuid> #include <QtCore/QUuid>
#include <QtCore/QVariantMap> #include <QtCore/QVariantMap>
@ -51,8 +52,7 @@ static const float MIN_AVATAR_SCALE = .005f;
const float MAX_AUDIO_LOUDNESS = 1000.0; // close enough for mouth animation const float MAX_AUDIO_LOUDNESS = 1000.0; // close enough for mouth animation
enum KeyState enum KeyState {
{
NO_KEY_DOWN = 0, NO_KEY_DOWN = 0,
INSERT_KEY_DOWN, INSERT_KEY_DOWN,
DELETE_KEY_DOWN DELETE_KEY_DOWN
@ -72,7 +72,9 @@ class AvatarData : public NodeData {
Q_PROPERTY(glm::quat orientation READ getOrientation WRITE setOrientation) Q_PROPERTY(glm::quat orientation READ getOrientation WRITE setOrientation)
Q_PROPERTY(float headPitch READ getHeadPitch WRITE setHeadPitch) 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: public:
AvatarData(); AvatarData();
~AvatarData(); ~AvatarData();
@ -142,6 +144,14 @@ public:
return false; return false;
} }
bool hasIdentityChangedAfterParsing(const QByteArray& packet);
QByteArray identityByteArray();
const QUrl& getFaceModelURL() const { return _faceModelURL; }
const QUrl& getSkeletonModelURL() const { return _skeletonModelURL; }
virtual void setFaceModelURL(const QUrl& faceModelURL);
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
protected: protected:
glm::vec3 _position; glm::vec3 _position;
glm::vec3 _handPosition; glm::vec3 _handPosition;
@ -168,6 +178,8 @@ protected:
HeadData* _headData; HeadData* _headData;
HandData* _handData; HandData* _handData;
QUrl _faceModelURL;
QUrl _skeletonModelURL;
private: private:
// privatize the copy constructor and assignment operator so they cannot be called // privatize the copy constructor and assignment operator so they cannot be called
AvatarData(const AvatarData&); AvatarData(const AvatarData&);

View file

@ -45,9 +45,8 @@ bool JurisdictionListener::queueJurisdictionRequest() {
NodeList* nodeList = NodeList::getInstance(); NodeList* nodeList = NodeList::getInstance();
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
if (nodeList->getNodeActiveSocketOrPing(node.data()) && node->getType() == getNodeType()) { if (nodeList->getNodeActiveSocketOrPing(node) && node->getType() == getNodeType()) {
const HifiSockAddr* nodeAddress = node->getActiveSocket(); _packetSender.queuePacketForSending(node, QByteArray(reinterpret_cast<char*>(bufferOut), sizeOut));
_packetSender.queuePacketForSending(*nodeAddress, QByteArray(reinterpret_cast<char*>(bufferOut), sizeOut));
nodeCount++; nodeCount++;
} }
} }
@ -62,16 +61,13 @@ bool JurisdictionListener::queueJurisdictionRequest() {
return isStillRunning(); return isStillRunning();
} }
void JurisdictionListener::processPacket(const HifiSockAddr& senderAddress, const QByteArray& packet) { void JurisdictionListener::processPacket(const SharedNodePointer& sendingNode, const QByteArray& packet) {
//qDebug() << "JurisdictionListener::processPacket()"; //qDebug() << "JurisdictionListener::processPacket()";
if (packetTypeForPacket(packet) == PacketTypeJurisdictionRequest) { if (packetTypeForPacket(packet) == PacketTypeJurisdictionRequest && sendingNode) {
SharedNodePointer node = NodeList::getInstance()->nodeWithAddress(senderAddress); QUuid nodeUUID = sendingNode->getUUID();
if (node) { JurisdictionMap map;
QUuid nodeUUID = node->getUUID(); map.unpackFromMessage(reinterpret_cast<const unsigned char*>(packet.data()), packet.size());
JurisdictionMap map; _jurisdictions[nodeUUID] = map;
map.unpackFromMessage(reinterpret_cast<const unsigned char*>(packet.data()), packet.size());
_jurisdictions[nodeUUID] = map;
}
} }
} }

View file

@ -49,7 +49,7 @@ protected:
/// \param packetData pointer to received data /// \param packetData pointer to received data
/// \param ssize_t packetLength size of received data /// \param ssize_t packetLength size of received data
/// \thread "this" individual processing thread /// \thread "this" individual processing thread
virtual void processPacket(const HifiSockAddr& senderAddress, const QByteArray& packet); virtual void processPacket(const SharedNodePointer& sendingNode, const QByteArray& packet);
private: private:
NodeToJurisdictionMap _jurisdictions; NodeToJurisdictionMap _jurisdictions;

View file

@ -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) { if (packetTypeForPacket(packet) == PacketTypeJurisdictionRequest) {
QUuid nodeUUID; if (sendingNode) {
deconstructPacketHeader(packet, nodeUUID);
if (!nodeUUID.isNull()) {
lockRequestingNodes(); lockRequestingNodes();
_nodesRequestingJurisdictions.push(nodeUUID); _nodesRequestingJurisdictions.push(sendingNode->getUUID());
unlockRequestingNodes(); unlockRequestingNodes();
} }
} }
@ -65,8 +63,7 @@ bool JurisdictionSender::process() {
SharedNodePointer node = NodeList::getInstance()->nodeWithUUID(nodeUUID); SharedNodePointer node = NodeList::getInstance()->nodeWithUUID(nodeUUID);
if (node && node->getActiveSocket() != NULL) { if (node && node->getActiveSocket() != NULL) {
const HifiSockAddr* nodeAddress = node->getActiveSocket(); _packetSender.queuePacketForSending(node, QByteArray(reinterpret_cast<char *>(bufferOut), sizeOut));
_packetSender.queuePacketForSending(*nodeAddress, QByteArray(reinterpret_cast<char *>(bufferOut), sizeOut));
nodeCount++; nodeCount++;
} }
} }

View file

@ -37,7 +37,7 @@ public:
void setNodeType(NodeType_t type) { _nodeType = type; } void setNodeType(NodeType_t type) { _nodeType = type; }
protected: 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. /// Locks all the resources of the thread.
void lockRequestingNodes() { _requestingNodeMutex.lock(); } void lockRequestingNodes() { _requestingNodeMutex.lock(); }

View file

@ -1347,7 +1347,7 @@ bool Octree::readFromSVOFile(const char* fileName) {
fileOk = true; // assume the file is ok fileOk = true; // assume the file is ok
} }
if (fileOk) { 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); readBitstreamToTree(dataAt, dataLength, args);
} }
delete[] entireFile; delete[] entireFile;
@ -1485,7 +1485,7 @@ void Octree::copyFromTreeIntoSubTree(Octree* sourceTree, OctreeElement* destinat
// ask destination tree to read the bitstream // ask destination tree to read the bitstream
bool wantImportProgress = true; 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); readBitstreamToTree(packetData.getUncompressedData(), packetData.getUncompressedSize(), args);
} }
} }

View file

@ -156,7 +156,7 @@ public:
bool includeExistsBits; bool includeExistsBits;
OctreeElement* destinationNode; OctreeElement* destinationNode;
QUuid sourceUUID; QUuid sourceUUID;
Node* sourceNode; SharedNodePointer sourceNode;
bool wantImportProgress; bool wantImportProgress;
ReadBitstreamToTreeParams( ReadBitstreamToTreeParams(
@ -164,7 +164,7 @@ public:
bool includeExistsBits = WANT_EXISTS_BITS, bool includeExistsBits = WANT_EXISTS_BITS,
OctreeElement* destinationNode = NULL, OctreeElement* destinationNode = NULL,
QUuid sourceUUID = QUuid(), QUuid sourceUUID = QUuid(),
Node* sourceNode = NULL, SharedNodePointer sourceNode = SharedNodePointer(),
bool wantImportProgress = false) : bool wantImportProgress = false) :
includeColor(includeColor), includeColor(includeColor),
includeExistsBits(includeExistsBits), includeExistsBits(includeExistsBits),
@ -190,7 +190,7 @@ public:
virtual PacketType expectedDataPacketType() const { return PacketTypeUnknown; } virtual PacketType expectedDataPacketType() const { return PacketTypeUnknown; }
virtual bool handlesEditPacketType(PacketType packetType) const { return false; } virtual bool handlesEditPacketType(PacketType packetType) const { return false; }
virtual int processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength, 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 virtual void update() { }; // nothing to do by default

View file

@ -61,7 +61,7 @@ bool OctreeEditPacketSender::serversExist() const {
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
// only send to the NodeTypes that are getMyNodeType() // only send to the NodeTypes that are getMyNodeType()
if (node->getType() == getMyNodeType()) { if (node->getType() == getMyNodeType()) {
if (nodeList->getNodeActiveSocketOrPing(node.data())) { if (nodeList->getNodeActiveSocketOrPing(node)) {
QUuid nodeUUID = node->getUUID(); QUuid nodeUUID = node->getUUID();
// If we've got Jurisdictions set, then check to see if we know the jurisdiction for this server // If we've got Jurisdictions set, then check to see if we know the jurisdiction for this server
if (_serverJurisdictions) { if (_serverJurisdictions) {
@ -91,9 +91,8 @@ void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned c
// only send to the NodeTypes that are getMyNodeType() // only send to the NodeTypes that are getMyNodeType()
if (node->getType() == getMyNodeType() && if (node->getType() == getMyNodeType() &&
((node->getUUID() == nodeUUID) || (nodeUUID.isNull()))) { ((node->getUUID() == nodeUUID) || (nodeUUID.isNull()))) {
if (nodeList->getNodeActiveSocketOrPing(node.data())) { if (nodeList->getNodeActiveSocketOrPing(node)) {
const HifiSockAddr* nodeAddress = node->getActiveSocket(); queuePacketForSending(node, QByteArray(reinterpret_cast<char*>(buffer), length));
queuePacketForSending(*nodeAddress, QByteArray(reinterpret_cast<char*>(buffer), length));
// debugging output... // debugging output...
bool wantDebugging = false; bool wantDebugging = false;

View file

@ -26,7 +26,7 @@ void OctreeRenderer::init() {
OctreeRenderer::~OctreeRenderer() { 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 showTimingDetails = false; // Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
bool extraDebugging = false; // Menu::getInstance()->isOptionChecked(MenuOption::ExtraDebugging) bool extraDebugging = false; // Menu::getInstance()->isOptionChecked(MenuOption::ExtraDebugging)
PerformanceWarning warn(showTimingDetails, "OctreeRenderer::processDatagram()",showTimingDetails); PerformanceWarning warn(showTimingDetails, "OctreeRenderer::processDatagram()",showTimingDetails);

View file

@ -43,7 +43,7 @@ public:
virtual void renderElement(OctreeElement* element, RenderArgs* args) = 0; virtual void renderElement(OctreeElement* element, RenderArgs* args) = 0;
/// process incoming data /// 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 /// initialize and GPU/rendering related resources
virtual void init(); virtual void init();

View file

@ -90,7 +90,7 @@ bool ParticleTree::findAndUpdateOperation(OctreeElement* element, void* extraDat
return true; 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.. // First, look for the existing particle in the tree..
FindAndUpdateParticleArgs args = { particle, false }; FindAndUpdateParticleArgs args = { particle, false };
recurseTreeWithOperation(findAndUpdateOperation, &args); 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()); float size = std::max(MINIMUM_PARTICLE_ELEMENT_SIZE, particle.getRadius());
ParticleTreeElement* element = (ParticleTreeElement*)getOrCreateChildElementAt(position.x, position.y, position.z, size); 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 // what else do we need to do here to get reaveraging to work
_isDirty = true; _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, 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; int processedBytes = 0;
// we handle these types of "edit" packets // we handle these types of "edit" packets
@ -415,7 +415,7 @@ int ParticleTree::processEditPacketData(PacketType packetType, const unsigned ch
return processedBytes; return processedBytes;
} }
void ParticleTree::notifyNewlyCreatedParticle(const Particle& newParticle, Node* senderNode) { void ParticleTree::notifyNewlyCreatedParticle(const Particle& newParticle, const SharedNodePointer& senderNode) {
_newlyCreatedHooksLock.lockForRead(); _newlyCreatedHooksLock.lockForRead();
for (size_t i = 0; i < _newlyCreatedHooks.size(); i++) { for (size_t i = 0; i < _newlyCreatedHooks.size(); i++) {
_newlyCreatedHooks[i]->particleCreated(newParticle, senderNode); _newlyCreatedHooks[i]->particleCreated(newParticle, senderNode);
@ -596,8 +596,7 @@ void ParticleTree::forgetParticlesDeletedBefore(quint64 sinceTime) {
} }
void ParticleTree::processEraseMessage(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr, void ParticleTree::processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) {
Node* sourceNode) {
const unsigned char* packetData = (const unsigned char*)dataByteArray.constData(); const unsigned char* packetData = (const unsigned char*)dataByteArray.constData();
const unsigned char* dataAt = packetData; const unsigned char* dataAt = packetData;

View file

@ -14,7 +14,7 @@
class NewlyCreatedParticleHook { class NewlyCreatedParticleHook {
public: public:
virtual void particleCreated(const Particle& newParticle, Node* senderNode) = 0; virtual void particleCreated(const Particle& newParticle, const SharedNodePointer& senderNode) = 0;
}; };
class ParticleTree : public Octree { class ParticleTree : public Octree {
@ -35,11 +35,11 @@ public:
virtual PacketType expectedDataPacketType() const { return PacketTypeParticleData; } virtual PacketType expectedDataPacketType() const { return PacketTypeParticleData; }
virtual bool handlesEditPacketType(PacketType packetType) const; virtual bool handlesEditPacketType(PacketType packetType) const;
virtual int processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength, 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(); 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 updateParticle(const ParticleID& particleID, const ParticleProperties& properties);
void addParticle(const ParticleID& particleID, const ParticleProperties& properties); void addParticle(const ParticleID& particleID, const ParticleProperties& properties);
void deleteParticle(const ParticleID& particleID); void deleteParticle(const ParticleID& particleID);
@ -67,7 +67,7 @@ public:
bool encodeParticlesDeletedSince(quint64& sinceTime, unsigned char* packetData, size_t maxLength, size_t& outputLength); bool encodeParticlesDeletedSince(quint64& sinceTime, unsigned char* packetData, size_t maxLength, size_t& outputLength);
void forgetParticlesDeletedBefore(quint64 sinceTime); 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); void handleAddParticleResponse(const QByteArray& packet);
private: private:
@ -82,7 +82,7 @@ private:
static bool findAndDeleteOperation(OctreeElement* element, void* extraData); static bool findAndDeleteOperation(OctreeElement* element, void* extraData);
static bool findAndUpdateParticleIDOperation(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; QReadWriteLock _newlyCreatedHooksLock;
std::vector<NewlyCreatedParticleHook*> _newlyCreatedHooks; std::vector<NewlyCreatedParticleHook*> _newlyCreatedHooks;

View file

@ -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); _particles->push_back(particle);
markWithChangedTime(); markWithChangedTime();
} }

View file

@ -121,7 +121,7 @@ public:
protected: protected:
virtual void init(unsigned char * octalCode); virtual void init(unsigned char * octalCode);
void storeParticle(const Particle& particle, Node* senderNode = NULL); void storeParticle(const Particle& particle);
ParticleTree* _myTree; ParticleTree* _myTree;
QList<Particle>* _particles; QList<Particle>* _particles;

View file

@ -1,21 +0,0 @@
//
// DataServerScriptingInterface.cpp
// hifi
//
// Created by Stephen Birarda on 1/20/2014.
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
//
#include <DataServerClient.h>
#include <NodeList.h>
#include "DataServerScriptingInterface.h"
DataServerScriptingInterface::DataServerScriptingInterface()
{
}
void DataServerScriptingInterface::setValueForKey(const QString& key, const QString& value) {
DataServerClient::putValueForKeyAndUUID(key, value, NodeList::getInstance()->getOwnerUUID());
}

View file

@ -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 <QtCore/QObject>
#include <QtCore/QUuid>
#include <QtScript/QScriptValue>
class DataServerScriptingInterface : public QObject {
Q_OBJECT
public:
DataServerScriptingInterface();
public slots:
void setValueForKey(const QString& key, const QString& value);
};
#endif /* defined(__hifi__DataServerScriptingInterface__) */

View file

@ -44,7 +44,6 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems, co
AbstractMenuInterface* menu, AbstractMenuInterface* menu,
AbstractControllerScriptingInterface* controllerScriptingInterface) : AbstractControllerScriptingInterface* controllerScriptingInterface) :
_isAvatar(false), _isAvatar(false),
_dataServerScriptingInterface(),
_avatarData(NULL) _avatarData(NULL)
{ {
_scriptContents = scriptContents; _scriptContents = scriptContents;
@ -137,7 +136,6 @@ void ScriptEngine::init() {
registerGlobalObject("Script", this); registerGlobalObject("Script", this);
registerGlobalObject("Audio", &_audioScriptingInterface); registerGlobalObject("Audio", &_audioScriptingInterface);
registerGlobalObject("Controller", _controllerScriptingInterface); registerGlobalObject("Controller", _controllerScriptingInterface);
registerGlobalObject("Data", &_dataServerScriptingInterface);
registerGlobalObject("Particles", &_particlesScriptingInterface); registerGlobalObject("Particles", &_particlesScriptingInterface);
registerGlobalObject("Quat", &_quatLibrary); registerGlobalObject("Quat", &_quatLibrary);
registerGlobalObject("Vec3", &_vec3Library); registerGlobalObject("Vec3", &_vec3Library);

View file

@ -24,7 +24,6 @@
class ParticlesScriptingInterface; class ParticlesScriptingInterface;
#include "AbstractControllerScriptingInterface.h" #include "AbstractControllerScriptingInterface.h"
#include "DataServerScriptingInterface.h"
#include "Quat.h" #include "Quat.h"
#include "Vec3.h" #include "Vec3.h"
@ -44,9 +43,6 @@ public:
/// Access the ParticlesScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener /// Access the ParticlesScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener
static ParticlesScriptingInterface* getParticlesScriptingInterface() { return &_particlesScriptingInterface; } 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 /// sets the script contents, will return false if failed, will fail if script is already running
bool setScriptContents(const QString& scriptContents); bool setScriptContents(const QString& scriptContents);
@ -98,7 +94,6 @@ private:
static ParticlesScriptingInterface _particlesScriptingInterface; static ParticlesScriptingInterface _particlesScriptingInterface;
AbstractControllerScriptingInterface* _controllerScriptingInterface; AbstractControllerScriptingInterface* _controllerScriptingInterface;
AudioScriptingInterface _audioScriptingInterface; AudioScriptingInterface _audioScriptingInterface;
DataServerScriptingInterface _dataServerScriptingInterface;
AvatarData* _avatarData; AvatarData* _avatarData;
bool _wantMenuItems; bool _wantMenuItems;
QString _scriptMenuName; QString _scriptMenuName;

View file

@ -52,8 +52,6 @@ private:
namespace DataServerKey { namespace DataServerKey {
const QString Domain = "domain"; const QString Domain = "domain";
const QString FaceMeshURL = "mesh";
const QString SkeletonURL = "skeleton";
const QString Position = "position"; const QString Position = "position";
const QString Orientation = "orientation"; const QString Orientation = "orientation";
const QString UUID = "uuid"; const QString UUID = "uuid";

View file

@ -8,15 +8,17 @@
// A really simple class that stores a network packet between being received and being processed // A really simple class that stores a network packet between being received and being processed
// //
#include <cassert>
#include <cstring> #include <cstring>
#include <QtDebug> #include <QtDebug>
#include <cassert>
#include "SharedUtil.h"
#include "NetworkPacket.h" #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) { if (packet.size() && packet.size() <= MAX_PACKET_SIZE) {
_sockAddr = sockAddr; _destinationNode = destinationNode;
_byteArray = packet; _byteArray = packet;
} else { } else {
qDebug(">>> NetworkPacket::copyContents() unexpected length = %d", packet.size()); qDebug(">>> NetworkPacket::copyContents() unexpected length = %d", packet.size());
@ -24,28 +26,28 @@ void NetworkPacket::copyContents(const HifiSockAddr& sockAddr, const QByteArray&
} }
NetworkPacket::NetworkPacket(const NetworkPacket& packet) { NetworkPacket::NetworkPacket(const NetworkPacket& packet) {
copyContents(packet.getSockAddr(), packet.getByteArray()); copyContents(packet.getDestinationNode(), packet.getByteArray());
} }
NetworkPacket::NetworkPacket(const HifiSockAddr& sockAddr, const QByteArray& packet) { NetworkPacket::NetworkPacket(const SharedNodePointer& destinationNode, const QByteArray& packet) {
copyContents(sockAddr, packet); copyContents(destinationNode, packet);
}; };
// copy assignment // copy assignment
NetworkPacket& NetworkPacket::operator=(NetworkPacket const& other) { NetworkPacket& NetworkPacket::operator=(NetworkPacket const& other) {
copyContents(other.getSockAddr(), other.getByteArray()); copyContents(other.getDestinationNode(), other.getByteArray());
return *this; return *this;
} }
#ifdef HAS_MOVE_SEMANTICS #ifdef HAS_MOVE_SEMANTICS
// move, same as copy, but other packet won't be used further // move, same as copy, but other packet won't be used further
NetworkPacket::NetworkPacket(NetworkPacket && packet) { NetworkPacket::NetworkPacket(NetworkPacket && packet) {
copyContents(packet.getAddress(), packet.getByteArray()); copyContents(packet.getDestinationNode(), packet.getByteArray());
} }
// move assignment // move assignment
NetworkPacket& NetworkPacket::operator=(NetworkPacket&& other) { NetworkPacket& NetworkPacket::operator=(NetworkPacket&& other) {
copyContents(other.getAddress(), other.getByteArray()); copyContents(other.getDestinationNode(), other.getByteArray());
return *this; return *this;
} }
#endif #endif

View file

@ -18,9 +18,7 @@
#include <ifaddrs.h> #include <ifaddrs.h>
#endif #endif
#include "HifiSockAddr.h" #include "NodeList.h"
#include "SharedUtil.h" // for MAX_PACKET_SIZE
/// Storage of not-yet processed inbound, or not yet sent outbound generic UDP network packet /// Storage of not-yet processed inbound, or not yet sent outbound generic UDP network packet
class NetworkPacket { class NetworkPacket {
@ -33,15 +31,15 @@ public:
NetworkPacket& operator= (NetworkPacket&& other); // move assignment NetworkPacket& operator= (NetworkPacket&& other); // move assignment
#endif #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; } const QByteArray& getByteArray() const { return _byteArray; }
private: private:
void copyContents(const HifiSockAddr& sockAddr, const QByteArray& byteArray); void copyContents(const SharedNodePointer& destinationNode, const QByteArray& byteArray);
HifiSockAddr _sockAddr; SharedNodePointer _destinationNode;
QByteArray _byteArray; QByteArray _byteArray;
}; };

View file

@ -52,6 +52,7 @@ Node::Node(const QUuid& uuid, char type, const HifiSockAddr& publicSocket, const
_publicSocket(publicSocket), _publicSocket(publicSocket),
_localSocket(localSocket), _localSocket(localSocket),
_activeSocket(NULL), _activeSocket(NULL),
_connectionSecret(),
_bytesReceivedMovingAverage(NULL), _bytesReceivedMovingAverage(NULL),
_linkedData(NULL), _linkedData(NULL),
_isAlive(true), _isAlive(true),

View file

@ -56,7 +56,6 @@ public:
char getType() const { return _type; } char getType() const { return _type; }
void setType(char type) { _type = type; } void setType(char type) { _type = type; }
const QUuid& getUUID() const { return _uuid; } const QUuid& getUUID() const { return _uuid; }
void setUUID(const QUuid& uuid) { _uuid = uuid; } void setUUID(const QUuid& uuid) { _uuid = uuid; }
@ -76,6 +75,9 @@ public:
void activatePublicSocket(); void activatePublicSocket();
void activateLocalSocket(); void activateLocalSocket();
const QUuid& getConnectionSecret() const { return _connectionSecret; }
void setConnectionSecret(const QUuid& connectionSecret) { _connectionSecret = connectionSecret; }
NodeData* getLinkedData() const { return _linkedData; } NodeData* getLinkedData() const { return _linkedData; }
void setLinkedData(NodeData* linkedData) { _linkedData = linkedData; } void setLinkedData(NodeData* linkedData) { _linkedData = linkedData; }
@ -109,6 +111,7 @@ private:
HifiSockAddr _publicSocket; HifiSockAddr _publicSocket;
HifiSockAddr _localSocket; HifiSockAddr _localSocket;
HifiSockAddr* _activeSocket; HifiSockAddr* _activeSocket;
QUuid _connectionSecret;
SimpleMovingAverage* _bytesReceivedMovingAverage; SimpleMovingAverage* _bytesReceivedMovingAverage;
NodeData* _linkedData; NodeData* _linkedData;
bool _isAlive; bool _isAlive;

View file

@ -64,7 +64,7 @@ NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) :
_nodeSocket(this), _nodeSocket(this),
_ownerType(newOwnerType), _ownerType(newOwnerType),
_nodeTypesOfInterest(), _nodeTypesOfInterest(),
_ownerUUID(QUuid::createUuid()), _sessionUUID(),
_numNoReplyDomainCheckIns(0), _numNoReplyDomainCheckIns(0),
_assignmentServerSocket(), _assignmentServerSocket(),
_publicSockAddr(), _publicSockAddr(),
@ -80,6 +80,37 @@ NodeList::~NodeList() {
clear(); 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 (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;
}
}
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) { void NodeList::setDomainHostname(const QString& domainHostname) {
if (domainHostname != _domainHostname) { if (domainHostname != _domainHostname) {
@ -111,13 +142,9 @@ void NodeList::setDomainHostname(const QString& domainHostname) {
} }
} }
void NodeList::timePingReply(const QByteArray& packet) { void NodeList::timePingReply(const QByteArray& packet, const SharedNodePointer& sendingNode) {
QUuid nodeUUID;
deconstructPacketHeader(packet, nodeUUID);
SharedNodePointer matchingNode = nodeWithUUID(nodeUUID); if (sendingNode) {
if (matchingNode) {
QDataStream packetStream(packet); QDataStream packetStream(packet);
packetStream.skipRawData(numBytesForPacketHeader(packet)); packetStream.skipRawData(numBytesForPacketHeader(packet));
@ -134,13 +161,13 @@ void NodeList::timePingReply(const QByteArray& packet) {
quint64 othersExprectedReply = ourOriginalTime + oneWayFlightTime; quint64 othersExprectedReply = ourOriginalTime + oneWayFlightTime;
int clockSkew = othersReplyTime - othersExprectedReply; int clockSkew = othersReplyTime - othersExprectedReply;
matchingNode->setPingMs(pingTime / 1000); sendingNode->setPingMs(pingTime / 1000);
matchingNode->setClockSkewUsec(clockSkew); sendingNode->setClockSkewUsec(clockSkew);
const bool wantDebug = false; const bool wantDebug = false;
if (wantDebug) { if (wantDebug) {
qDebug() << "PING_REPLY from node " << *matchingNode << "\n" << qDebug() << "PING_REPLY from node " << *sendingNode << "\n" <<
" now: " << now << "\n" << " now: " << now << "\n" <<
" ourTime: " << ourOriginalTime << "\n" << " ourTime: " << ourOriginalTime << "\n" <<
" pingTime: " << pingTime << "\n" << " pingTime: " << pingTime << "\n" <<
@ -165,15 +192,20 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr
case PacketTypePing: { case PacketTypePing: {
// send back a reply // send back a reply
QByteArray replyPacket = constructPingReplyPacket(packet); QByteArray replyPacket = constructPingReplyPacket(packet);
_nodeSocket.writeDatagram(replyPacket, senderSockAddr.getAddress(), senderSockAddr.getPort()); writeDatagram(replyPacket, sendingNodeForPacket(packet), senderSockAddr);
break; break;
} }
case PacketTypePingReply: { case PacketTypePingReply: {
// activate the appropriate socket for this node, if not yet updated SharedNodePointer sendingNode = sendingNodeForPacket(packet);
activateSocketFromNodeCommunication(senderSockAddr);
if (sendingNode) {
// set the ping time for this node for stat collection // activate the appropriate socket for this node, if not yet updated
timePingReply(packet); activateSocketFromNodeCommunication(packet, sendingNode);
// set the ping time for this node for stat collection
timePingReply(packet, sendingNode);
}
break; break;
} }
case PacketTypeStunResponse: { case PacketTypeStunResponse: {
@ -215,23 +247,18 @@ 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) { SharedNodePointer NodeList::nodeWithUUID(const QUuid& nodeUUID) {
QMutexLocker locker(&_nodeHashMutex); QMutexLocker locker(&_nodeHashMutex);
return _nodeHash.value(nodeUUID); return _nodeHash.value(nodeUUID);
} }
SharedNodePointer NodeList::sendingNodeForPacket(const QByteArray& packet) {
QUuid nodeUUID = uuidFromPacketHeader(packet);
// return the matching node, or NULL if there is no match
return nodeWithUUID(nodeUUID);
}
NodeHash NodeList::getNodeHash() { NodeHash NodeList::getNodeHash() {
QMutexLocker locker(&_nodeHashMutex); QMutexLocker locker(&_nodeHashMutex);
return NodeHash(_nodeHash); return NodeHash(_nodeHash);
@ -257,7 +284,7 @@ void NodeList::reset() {
_nodeTypesOfInterest.clear(); _nodeTypesOfInterest.clear();
// refresh the owner UUID // refresh the owner UUID
_ownerUUID = QUuid::createUuid(); _sessionUUID = QUuid::createUuid();
} }
void NodeList::addNodeTypeToInterestSet(NodeType_t nodeTypeToAdd) { void NodeList::addNodeTypeToInterestSet(NodeType_t nodeTypeToAdd) {
@ -492,6 +519,16 @@ void NodeList::sendDomainServerCheckIn() {
} }
} }
void NodeList::setSessionUUID(const QUuid& sessionUUID) {
QUuid oldUUID = _sessionUUID;
_sessionUUID = sessionUUID;
if (sessionUUID != oldUUID) {
qDebug() << "NodeList UUID changed from" << oldUUID << "to" << _sessionUUID;
emit uuidChanged(sessionUUID);
}
}
int NodeList::processDomainServerList(const QByteArray& packet) { int NodeList::processDomainServerList(const QByteArray& packet) {
// this is a packet from the domain server, reset the count of un-replied check-ins // this is a packet from the domain server, reset the count of un-replied check-ins
_numNoReplyDomainCheckIns = 0; _numNoReplyDomainCheckIns = 0;
@ -501,14 +538,20 @@ int NodeList::processDomainServerList(const QByteArray& packet) {
// setup variables to read into from QDataStream // setup variables to read into from QDataStream
qint8 nodeType; qint8 nodeType;
QUuid nodeUUID; QUuid nodeUUID, connectionUUID;
HifiSockAddr nodePublicSocket; HifiSockAddr nodePublicSocket;
HifiSockAddr nodeLocalSocket; HifiSockAddr nodeLocalSocket;
QDataStream packetStream(packet); QDataStream packetStream(packet);
packetStream.skipRawData(numBytesForPacketHeader(packet)); packetStream.skipRawData(numBytesForPacketHeader(packet));
// pull our owner UUID from the packet, it's always the first thing
QUuid newUUID;
packetStream >> newUUID;
setSessionUUID(newUUID);
// pull each node in the packet
while(packetStream.device()->pos() < packet.size()) { while(packetStream.device()->pos() < packet.size()) {
packetStream >> nodeType >> nodeUUID >> nodePublicSocket >> nodeLocalSocket; packetStream >> nodeType >> nodeUUID >> nodePublicSocket >> nodeLocalSocket;
@ -518,7 +561,10 @@ int NodeList::processDomainServerList(const QByteArray& packet) {
nodePublicSocket.setAddress(_domainSockAddr.getAddress()); nodePublicSocket.setAddress(_domainSockAddr.getAddress());
} }
addOrUpdateNode(nodeUUID, nodeType, nodePublicSocket, nodeLocalSocket); SharedNodePointer node = addOrUpdateNode(nodeUUID, nodeType, nodePublicSocket, nodeLocalSocket);
packetStream >> connectionUUID;
node->setConnectionSecret(connectionUUID);
} }
return readNodes; return readNodes;
@ -544,10 +590,12 @@ void NodeList::sendAssignment(Assignment& assignment) {
_nodeSocket.writeDatagram(packet, assignmentServerSocket->getAddress(), assignmentServerSocket->getPort()); _nodeSocket.writeDatagram(packet, assignmentServerSocket->getAddress(), assignmentServerSocket->getPort());
} }
QByteArray NodeList::constructPingPacket() { QByteArray NodeList::constructPingPacket(PingType_t pingType) {
QByteArray pingPacket = byteArrayWithPopluatedHeader(PacketTypePing); QByteArray pingPacket = byteArrayWithPopluatedHeader(PacketTypePing);
QDataStream packetStream(&pingPacket, QIODevice::Append); QDataStream packetStream(&pingPacket, QIODevice::Append);
packetStream << pingType;
packetStream << usecTimestampNow(); packetStream << usecTimestampNow();
return pingPacket; return pingPacket;
@ -557,23 +605,28 @@ QByteArray NodeList::constructPingReplyPacket(const QByteArray& pingPacket) {
QDataStream pingPacketStream(pingPacket); QDataStream pingPacketStream(pingPacket);
pingPacketStream.skipRawData(numBytesForPacketHeader(pingPacket)); pingPacketStream.skipRawData(numBytesForPacketHeader(pingPacket));
PingType_t typeFromOriginalPing;
pingPacketStream >> typeFromOriginalPing;
quint64 timeFromOriginalPing; quint64 timeFromOriginalPing;
pingPacketStream >> timeFromOriginalPing; pingPacketStream >> timeFromOriginalPing;
QByteArray replyPacket = byteArrayWithPopluatedHeader(PacketTypePingReply); QByteArray replyPacket = byteArrayWithPopluatedHeader(PacketTypePingReply);
QDataStream packetStream(&replyPacket, QIODevice::Append); QDataStream packetStream(&replyPacket, QIODevice::Append);
packetStream << timeFromOriginalPing << usecTimestampNow(); packetStream << typeFromOriginalPing << timeFromOriginalPing << usecTimestampNow();
return replyPacket; 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 // send the ping packet to the local and public sockets for this node
_nodeSocket.writeDatagram(pingPacket, node->getLocalSocket().getAddress(), node->getLocalSocket().getPort()); QByteArray localPingPacket = constructPingPacket(PingType::Local);
_nodeSocket.writeDatagram(pingPacket, node->getPublicSocket().getAddress(), node->getPublicSocket().getPort()); writeDatagram(localPingPacket, node, node->getLocalSocket());
QByteArray publicPingPacket = constructPingPacket(PingType::Public);
writeDatagram(publicPingPacket, node, node->getPublicSocket());
} }
SharedNodePointer NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, SharedNodePointer NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType,
@ -630,11 +683,8 @@ unsigned NodeList::broadcastToNodes(const QByteArray& packet, const NodeSet& des
foreach (const SharedNodePointer& node, getNodeHash()) { foreach (const SharedNodePointer& node, getNodeHash()) {
// only send to the NodeTypes we are asked to send to. // only send to the NodeTypes we are asked to send to.
if (destinationNodeTypes.contains(node->getType())) { if (destinationNodeTypes.contains(node->getType())) {
if (getNodeActiveSocketOrPing(node.data())) { writeDatagram(packet, node);
// we know which socket is good for this node, send there ++n;
_nodeSocket.writeDatagram(packet, node->getActiveSocket()->getAddress(), node->getActiveSocket()->getPort());
++n;
}
} }
} }
@ -645,34 +695,35 @@ void NodeList::pingInactiveNodes() {
foreach (const SharedNodePointer& node, getNodeHash()) { foreach (const SharedNodePointer& node, getNodeHash()) {
if (!node->getActiveSocket()) { if (!node->getActiveSocket()) {
// we don't have an active link to this node, ping it to set that up // 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) { const HifiSockAddr* NodeList::getNodeActiveSocketOrPing(const SharedNodePointer& node) {
if (node->getActiveSocket()) { if (node && node->getActiveSocket()) {
return node->getActiveSocket(); return node->getActiveSocket();
} else { } else if (node) {
pingPublicAndLocalSocketsForInactiveNode(node); pingPublicAndLocalSocketsForInactiveNode(node);
return NULL;
} }
return NULL;
} }
void NodeList::activateSocketFromNodeCommunication(const HifiSockAddr& nodeAddress) { void NodeList::activateSocketFromNodeCommunication(const QByteArray& packet, const SharedNodePointer& sendingNode) {
// deconstruct this ping packet to see if it is a public or local reply
foreach (const SharedNodePointer& node, _nodeHash) { QDataStream packetStream(packet);
if (!node->getActiveSocket()) { packetStream.skipRawData(numBytesForPacketHeader(packet));
// 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 quint8 pingType;
if (node->getPublicSocket() == nodeAddress) { packetStream >> pingType;
node->activatePublicSocket();
break; // if this is a local or public ping then we can activate a socket
} else if (node->getLocalSocket() == nodeAddress) { // we do nothing with agnostic pings, those are simply for timing
node->activateLocalSocket(); if (pingType == PingType::Local) {
break; sendingNode->activateLocalSocket();
} } else if (pingType == PingType::Public) {
} sendingNode->activatePublicSocket();
} }
} }

View file

@ -52,6 +52,13 @@ typedef QSharedPointer<Node> SharedNodePointer;
typedef QHash<QUuid, SharedNodePointer> NodeHash; typedef QHash<QUuid, SharedNodePointer> NodeHash;
Q_DECLARE_METATYPE(SharedNodePointer) 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 { class NodeList : public QObject {
Q_OBJECT Q_OBJECT
public: public:
@ -70,10 +77,15 @@ public:
unsigned short getDomainPort() const { return _domainSockAddr.getPort(); } unsigned short getDomainPort() const { return _domainSockAddr.getPort(); }
const QUuid& getOwnerUUID() const { return _ownerUUID; } const QUuid& getSessionUUID() const { return _sessionUUID; }
void setOwnerUUID(const QUuid& ownerUUID) { _ownerUUID = ownerUUID; } void setSessionUUID(const QUuid& sessionUUID);
QUdpSocket& getNodeSocket() { return _nodeSocket; } 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 *); void(*linkedDataCreateCallback)(Node *);
@ -93,13 +105,13 @@ public:
void setAssignmentServerSocket(const HifiSockAddr& serverSocket) { _assignmentServerSocket = serverSocket; } void setAssignmentServerSocket(const HifiSockAddr& serverSocket) { _assignmentServerSocket = serverSocket; }
void sendAssignment(Assignment& assignment); void sendAssignment(Assignment& assignment);
QByteArray constructPingPacket(); QByteArray constructPingPacket(PingType_t pingType = PingType::Agnostic);
QByteArray constructPingReplyPacket(const QByteArray& pingPacket); QByteArray constructPingReplyPacket(const QByteArray& pingPacket);
void pingPublicAndLocalSocketsForInactiveNode(Node* node); void pingPublicAndLocalSocketsForInactiveNode(const SharedNodePointer& node);
SharedNodePointer nodeWithAddress(const HifiSockAddr& senderSockAddr);
SharedNodePointer nodeWithUUID(const QUuid& nodeUUID); 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 processNodeData(const HifiSockAddr& senderSockAddr, const QByteArray& packet);
@ -113,7 +125,7 @@ public:
void loadData(QSettings* settings); void loadData(QSettings* settings);
void saveData(QSettings* settings); void saveData(QSettings* settings);
const HifiSockAddr* getNodeActiveSocketOrPing(Node* node); const HifiSockAddr* getNodeActiveSocketOrPing(const SharedNodePointer& node);
public slots: public slots:
void sendDomainServerCheckIn(); void sendDomainServerCheckIn();
void pingInactiveNodes(); void pingInactiveNodes();
@ -122,6 +134,7 @@ public slots:
void killNodeWithUUID(const QUuid& nodeUUID); void killNodeWithUUID(const QUuid& nodeUUID);
signals: signals:
void domainChanged(const QString& domainHostname); void domainChanged(const QString& domainHostname);
void uuidChanged(const QUuid& ownerUUID);
void nodeAdded(SharedNodePointer); void nodeAdded(SharedNodePointer);
void nodeKilled(SharedNodePointer); void nodeKilled(SharedNodePointer);
private: private:
@ -143,15 +156,15 @@ private:
QUdpSocket _nodeSocket; QUdpSocket _nodeSocket;
NodeType_t _ownerType; NodeType_t _ownerType;
NodeSet _nodeTypesOfInterest; NodeSet _nodeTypesOfInterest;
QUuid _ownerUUID; QUuid _sessionUUID;
int _numNoReplyDomainCheckIns; int _numNoReplyDomainCheckIns;
HifiSockAddr _assignmentServerSocket; HifiSockAddr _assignmentServerSocket;
HifiSockAddr _publicSockAddr; HifiSockAddr _publicSockAddr;
bool _hasCompletedInitialSTUNFailure; bool _hasCompletedInitialSTUNFailure;
unsigned int _stunRequestsSinceSuccess; unsigned int _stunRequestsSinceSuccess;
void activateSocketFromNodeCommunication(const HifiSockAddr& nodeSockAddr); void activateSocketFromNodeCommunication(const QByteArray& packet, const SharedNodePointer& sendingNode);
void timePingReply(const QByteArray& packet); void timePingReply(const QByteArray& packet, const SharedNodePointer& sendingNode);
void resetDomainData(char domainField[], const char* domainData); void resetDomainData(char domainField[], const char* domainData);
void domainLookup(); void domainLookup();
void clear(); void clear();

View file

@ -69,13 +69,20 @@ int populatePacketHeader(char* packet, PacketType type, const QUuid& connectionU
int numTypeBytes = packArithmeticallyCodedValue(type, packet); int numTypeBytes = packArithmeticallyCodedValue(type, packet);
packet[numTypeBytes] = versionForPacketType(type); packet[numTypeBytes] = versionForPacketType(type);
QUuid packUUID = connectionUUID.isNull() ? NodeList::getInstance()->getOwnerUUID() : connectionUUID; char* position = packet + numTypeBytes + sizeof(PacketVersion);
QUuid packUUID = connectionUUID.isNull() ? NodeList::getInstance()->getSessionUUID() : connectionUUID;
QByteArray rfcUUID = packUUID.toRfc4122(); 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 the number of bytes written for pointer pushing
return numTypeBytes + sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID; return position - packet;
} }
bool packetVersionMatch(const QByteArray& packet) { bool packetVersionMatch(const QByteArray& packet) {
@ -88,8 +95,7 @@ bool packetVersionMatch(const QByteArray& packet) {
PacketType mismatchType = packetTypeForPacket(packet); PacketType mismatchType = packetTypeForPacket(packet);
int numPacketTypeBytes = arithmeticCodingValueFromBuffer(packet.data()); int numPacketTypeBytes = arithmeticCodingValueFromBuffer(packet.data());
QUuid nodeUUID; QUuid nodeUUID = uuidFromPacketHeader(packet);
deconstructPacketHeader(packet, nodeUUID);
qDebug() << "Packet mismatch on" << packetTypeForPacket(packet) << "- Sender" qDebug() << "Packet mismatch on" << packetTypeForPacket(packet) << "- Sender"
<< nodeUUID << "sent" << qPrintable(QString::number(packet[numPacketTypeBytes])) << "but" << nodeUUID << "sent" << qPrintable(QString::number(packet[numPacketTypeBytes])) << "but"
@ -101,21 +107,21 @@ bool packetVersionMatch(const QByteArray& packet) {
int numBytesForPacketHeader(const QByteArray& packet) { int numBytesForPacketHeader(const QByteArray& packet) {
// returns the number of bytes used for the type, version, and UUID // 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) { int numBytesForPacketHeader(const char* packet) {
// returns the number of bytes used for the type, version, and UUID // 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) { 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) { QUuid uuidFromPacketHeader(const QByteArray& packet) {
senderUUID = QUuid::fromRfc4122(packet.mid(numBytesArithmeticCodingFromBuffer(packet.data()) + sizeof(PacketVersion), return QUuid::fromRfc4122(packet.mid(numBytesArithmeticCodingFromBuffer(packet.data()) + sizeof(PacketVersion),
NUM_BYTES_RFC4122_UUID)); NUM_BYTES_RFC4122_UUID));
} }
PacketType packetTypeForPacket(const QByteArray& packet) { PacketType packetTypeForPacket(const QByteArray& packet) {

View file

@ -12,6 +12,7 @@
#ifndef hifi_PacketHeaders_h #ifndef hifi_PacketHeaders_h
#define hifi_PacketHeaders_h #define hifi_PacketHeaders_h
#include <QtCore/QCryptographicHash>
#include <QtCore/QUuid> #include <QtCore/QUuid>
#include "UUID.h" #include "UUID.h"
@ -51,12 +52,15 @@ enum PacketType {
PacketTypeParticleAddOrEdit, PacketTypeParticleAddOrEdit,
PacketTypeParticleErase, PacketTypeParticleErase,
PacketTypeParticleAddResponse, PacketTypeParticleAddResponse,
PacketTypeMetavoxelData PacketTypeMetavoxelData,
PacketTypeAvatarIdentity
}; };
typedef char PacketVersion; 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); PacketVersion versionForPacketType(PacketType type);
@ -72,7 +76,7 @@ int numBytesForPacketHeader(const QByteArray& packet);
int numBytesForPacketHeader(const char* packet); int numBytesForPacketHeader(const char* packet);
int numBytesForPacketHeaderGivenPacketType(PacketType type); int numBytesForPacketHeaderGivenPacketType(PacketType type);
void deconstructPacketHeader(const QByteArray& packet, QUuid& senderUUID); QUuid uuidFromPacketHeader(const QByteArray& packet);
PacketType packetTypeForPacket(const QByteArray& packet); PacketType packetTypeForPacket(const QByteArray& packet);
PacketType packetTypeForPacket(const char* packet); PacketType packetTypeForPacket(const char* packet);

View file

@ -47,8 +47,8 @@ PacketSender::~PacketSender() {
} }
void PacketSender::queuePacketForSending(const HifiSockAddr& address, const QByteArray& packet) { void PacketSender::queuePacketForSending(const SharedNodePointer& destinationNode, const QByteArray& packet) {
NetworkPacket networkPacket(address, packet); NetworkPacket networkPacket(destinationNode, packet);
lock(); lock();
_packets.push_back(networkPacket); _packets.push_back(networkPacket);
unlock(); unlock();
@ -263,9 +263,7 @@ bool PacketSender::nonThreadedProcess() {
unlock(); unlock();
// send the packet through the NodeList... // send the packet through the NodeList...
NodeList::getInstance()->getNodeSocket().writeDatagram(temporary.getByteArray(), NodeList::getInstance()->writeDatagram(temporary.getByteArray(), temporary.getDestinationNode());
temporary.getSockAddr().getAddress(),
temporary.getSockAddr().getPort());
packetsSentThisCall++; packetsSentThisCall++;
_packetsOverCheckInterval++; _packetsOverCheckInterval++;
_totalPacketsSent++; _totalPacketsSent++;

View file

@ -38,7 +38,7 @@ public:
/// \param packetData pointer to data /// \param packetData pointer to data
/// \param ssize_t packetLength size of data /// \param ssize_t packetLength size of data
/// \thread any thread, typically the application thread /// \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); void setPacketsPerSecond(int packetsPerSecond);
int getPacketsPerSecond() const { return _packetsPerSecond; } int getPacketsPerSecond() const { return _packetsPerSecond; }

View file

@ -16,14 +16,11 @@ ReceivedPacketProcessor::ReceivedPacketProcessor() {
_dontSleep = false; _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. // Make sure our Node and NodeList knows we've heard from this node.
SharedNodePointer node = NodeList::getInstance()->nodeWithAddress(address); destinationNode->setLastHeardMicrostamp(usecTimestampNow());
if (node) {
node->setLastHeardMicrostamp(usecTimestampNow());
}
NetworkPacket networkPacket(address, packet); NetworkPacket networkPacket(destinationNode, packet);
lock(); lock();
_packets.push_back(networkPacket); _packets.push_back(networkPacket);
unlock(); unlock();
@ -44,7 +41,7 @@ bool ReceivedPacketProcessor::process() {
NetworkPacket temporary = packet; // make a copy of the packet in case the vector is resized on us 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 _packets.erase(_packets.begin()); // remove the oldest packet
unlock(); // let others add to the packets unlock(); // let others add to the packets
processPacket(temporary.getSockAddr(), temporary.getByteArray()); // process our temporary copy processPacket(temporary.getDestinationNode(), temporary.getByteArray()); // process our temporary copy
} }
return isStillRunning(); // keep running till they terminate us return isStillRunning(); // keep running till they terminate us
} }

View file

@ -24,7 +24,7 @@ public:
/// \param packetData pointer to received data /// \param packetData pointer to received data
/// \param ssize_t packetLength size of received data /// \param ssize_t packetLength size of received data
/// \thread network receive thread /// \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 /// Are there received packets waiting to be processed
bool hasPacketsToProcess() const { return _packets.size() > 0; } bool hasPacketsToProcess() const { return _packets.size() > 0; }
@ -38,7 +38,7 @@ protected:
/// \param packetData pointer to received data /// \param packetData pointer to received data
/// \param ssize_t packetLength size of received data /// \param ssize_t packetLength size of received data
/// \thread "this" individual processing thread /// \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. /// Implements generic processing behavior for this thread.
virtual bool process(); virtual bool process();

View file

@ -522,7 +522,7 @@ bool VoxelTree::handlesEditPacketType(PacketType packetType) const {
} }
int VoxelTree::processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength, 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 // we handle these types of "edit" packets
switch (packetType) { switch (packetType) {

View file

@ -54,7 +54,7 @@ public:
virtual PacketType expectedDataPacketType() const { return PacketTypeVoxelData; } virtual PacketType expectedDataPacketType() const { return PacketTypeVoxelData; }
virtual bool handlesEditPacketType(PacketType packetType) const; virtual bool handlesEditPacketType(PacketType packetType) const;
virtual int processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength, 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); void processSetVoxelsBitstream(const unsigned char* bitstream, int bufferSizeBytes);
/** /**