Merge branch 'master' of https://github.com/highfidelity/hifi into inline-entity-scripts

This commit is contained in:
Howard Stearns 2015-05-11 10:32:15 -07:00
commit 0474477399
34 changed files with 477 additions and 208 deletions

View file

@ -88,7 +88,7 @@ void AssignmentClientMonitor::stopChildProcesses() {
nodeList->eachNode([&](const SharedNodePointer& node) { nodeList->eachNode([&](const SharedNodePointer& node) {
qDebug() << "asking child" << node->getUUID() << "to exit."; qDebug() << "asking child" << node->getUUID() << "to exit.";
node->activateLocalSocket(); node->activateLocalSocket();
QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); QByteArray diePacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeStopNode);
nodeList->writeUnverifiedDatagram(diePacket, *node->getActiveSocket()); nodeList->writeUnverifiedDatagram(diePacket, *node->getActiveSocket());
}); });
@ -193,7 +193,7 @@ void AssignmentClientMonitor::checkSpares() {
qDebug() << "asking child" << aSpareId << "to exit."; qDebug() << "asking child" << aSpareId << "to exit.";
SharedNodePointer childNode = nodeList->nodeWithUUID(aSpareId); SharedNodePointer childNode = nodeList->nodeWithUUID(aSpareId);
childNode->activateLocalSocket(); childNode->activateLocalSocket();
QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); QByteArray diePacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeStopNode);
nodeList->writeUnverifiedDatagram(diePacket, childNode); nodeList->writeUnverifiedDatagram(diePacket, childNode);
} }
} }
@ -229,7 +229,7 @@ void AssignmentClientMonitor::readPendingDatagrams() {
} else { } else {
// tell unknown assignment-client child to exit. // tell unknown assignment-client child to exit.
qDebug() << "asking unknown child to exit."; qDebug() << "asking unknown child to exit.";
QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); QByteArray diePacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeStopNode);
nodeList->writeUnverifiedDatagram(diePacket, senderSockAddr); nodeList->writeUnverifiedDatagram(diePacket, senderSockAddr);
} }
} }

View file

@ -65,12 +65,6 @@ const QString AUDIO_MIXER_LOGGING_TARGET_NAME = "audio-mixer";
const QString AUDIO_ENV_GROUP_KEY = "audio_env"; const QString AUDIO_ENV_GROUP_KEY = "audio_env";
const QString AUDIO_BUFFER_GROUP_KEY = "audio_buffer"; const QString AUDIO_BUFFER_GROUP_KEY = "audio_buffer";
void attachNewNodeDataToNode(Node *newNode) {
if (!newNode->getLinkedData()) {
newNode->setLinkedData(new AudioMixerClientData());
}
}
InboundAudioStream::Settings AudioMixer::_streamSettings; InboundAudioStream::Settings AudioMixer::_streamSettings;
bool AudioMixer::_printStreamStats = false; bool AudioMixer::_printStreamStats = false;
@ -514,7 +508,8 @@ void AudioMixer::sendAudioEnvironmentPacket(SharedNodePointer node) {
bool sendData = dataChanged || (randFloat() < CHANCE_OF_SEND); bool sendData = dataChanged || (randFloat() < CHANCE_OF_SEND);
if (sendData) { if (sendData) {
int numBytesEnvPacketHeader = populatePacketHeader(clientEnvBuffer, PacketTypeAudioEnvironment); auto nodeList = DependencyManager::get<NodeList>();
int numBytesEnvPacketHeader = nodeList->populatePacketHeader(clientEnvBuffer, PacketTypeAudioEnvironment);
char* envDataAt = clientEnvBuffer + numBytesEnvPacketHeader; char* envDataAt = clientEnvBuffer + numBytesEnvPacketHeader;
unsigned char bitset = 0; unsigned char bitset = 0;
@ -531,7 +526,7 @@ void AudioMixer::sendAudioEnvironmentPacket(SharedNodePointer node) {
memcpy(envDataAt, &wetLevel, sizeof(float)); memcpy(envDataAt, &wetLevel, sizeof(float));
envDataAt += sizeof(float); envDataAt += sizeof(float);
} }
DependencyManager::get<NodeList>()->writeDatagram(clientEnvBuffer, envDataAt - clientEnvBuffer, node); nodeList->writeDatagram(clientEnvBuffer, envDataAt - clientEnvBuffer, node);
} }
} }
@ -552,7 +547,7 @@ void AudioMixer::readPendingDatagram(const QByteArray& receivedPacket, const Hif
SharedNodePointer sendingNode = nodeList->sendingNodeForPacket(receivedPacket); SharedNodePointer sendingNode = nodeList->sendingNodeForPacket(receivedPacket);
if (sendingNode->getCanAdjustLocks()) { if (sendingNode->getCanAdjustLocks()) {
QByteArray packet = receivedPacket; QByteArray packet = receivedPacket;
populatePacketHeader(packet, PacketTypeMuteEnvironment); nodeList->populatePacketHeader(packet, PacketTypeMuteEnvironment);
nodeList->eachNode([&](const SharedNodePointer& node){ nodeList->eachNode([&](const SharedNodePointer& node){
if (node->getType() == NodeType::Agent && node->getActiveSocket() && if (node->getType() == NodeType::Agent && node->getActiveSocket() &&
@ -686,7 +681,9 @@ void AudioMixer::run() {
nodeList->addNodeTypeToInterestSet(NodeType::Agent); nodeList->addNodeTypeToInterestSet(NodeType::Agent);
nodeList->linkedDataCreateCallback = attachNewNodeDataToNode; nodeList->linkedDataCreateCallback = [](Node* node) {
node->setLinkedData(new AudioMixerClientData());
};
// wait until we have the domain-server settings, otherwise we bail // wait until we have the domain-server settings, otherwise we bail
DomainHandler& domainHandler = nodeList->getDomainHandler(); DomainHandler& domainHandler = nodeList->getDomainHandler();
@ -794,7 +791,7 @@ void AudioMixer::run() {
// if the stream should be muted, send mute packet // if the stream should be muted, send mute packet
if (nodeData->getAvatarAudioStream() if (nodeData->getAvatarAudioStream()
&& shouldMute(nodeData->getAvatarAudioStream()->getQuietestFrameLoudness())) { && shouldMute(nodeData->getAvatarAudioStream()->getQuietestFrameLoudness())) {
QByteArray packet = byteArrayWithPopulatedHeader(PacketTypeNoisyMute); QByteArray packet = nodeList->byteArrayWithPopulatedHeader(PacketTypeNoisyMute);
nodeList->writeDatagram(packet, node); nodeList->writeDatagram(packet, node);
} }
@ -806,7 +803,7 @@ void AudioMixer::run() {
char* mixDataAt; char* mixDataAt;
if (streamsMixed > 0) { if (streamsMixed > 0) {
// pack header // pack header
int numBytesMixPacketHeader = populatePacketHeader(clientMixBuffer, PacketTypeMixedAudio); int numBytesMixPacketHeader = nodeList->populatePacketHeader(clientMixBuffer, PacketTypeMixedAudio);
mixDataAt = clientMixBuffer + numBytesMixPacketHeader; mixDataAt = clientMixBuffer + numBytesMixPacketHeader;
// pack sequence number // pack sequence number
@ -819,7 +816,7 @@ void AudioMixer::run() {
mixDataAt += AudioConstants::NETWORK_FRAME_BYTES_STEREO; mixDataAt += AudioConstants::NETWORK_FRAME_BYTES_STEREO;
} else { } else {
// pack header // pack header
int numBytesPacketHeader = populatePacketHeader(clientMixBuffer, PacketTypeSilentAudioFrame); int numBytesPacketHeader = nodeList->populatePacketHeader(clientMixBuffer, PacketTypeSilentAudioFrame);
mixDataAt = clientMixBuffer + numBytesPacketHeader; mixDataAt = clientMixBuffer + numBytesPacketHeader;
// pack sequence number // pack sequence number

View file

@ -157,7 +157,7 @@ void AudioMixerClientData::sendAudioStreamStatsPackets(const SharedNodePointer&
quint8 appendFlag = 0; quint8 appendFlag = 0;
// pack header // pack header
int numBytesPacketHeader = populatePacketHeader(packet, PacketTypeAudioStreamStats); int numBytesPacketHeader = nodeList->populatePacketHeader(packet, PacketTypeAudioStreamStats);
char* headerEndAt = packet + numBytesPacketHeader; char* headerEndAt = packet + numBytesPacketHeader;
// calculate how many stream stat structs we can fit in each packet // calculate how many stream stat structs we can fit in each packet

View file

@ -56,14 +56,6 @@ AvatarMixer::~AvatarMixer() {
_broadcastThread.wait(); _broadcastThread.wait();
} }
void attachAvatarDataToNode(Node* newNode) {
if (!newNode->getLinkedData()) {
// setup the client linked data - default the number of frames since adjustment
// to our number of frames per second
newNode->setLinkedData(new AvatarMixerClientData());
}
}
const float BILLBOARD_AND_IDENTITY_SEND_PROBABILITY = 1.0f / 300.0f; const float BILLBOARD_AND_IDENTITY_SEND_PROBABILITY = 1.0f / 300.0f;
// NOTE: some additional optimizations to consider. // NOTE: some additional optimizations to consider.
@ -129,10 +121,9 @@ void AvatarMixer::broadcastAvatarData() {
static QByteArray mixedAvatarByteArray; static QByteArray mixedAvatarByteArray;
int numPacketHeaderBytes = populatePacketHeader(mixedAvatarByteArray, PacketTypeBulkAvatarData);
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
int numPacketHeaderBytes = nodeList->populatePacketHeader(mixedAvatarByteArray, PacketTypeBulkAvatarData);
// setup for distributed random floating point values // setup for distributed random floating point values
std::random_device randomDevice; std::random_device randomDevice;
std::mt19937 generator(randomDevice()); std::mt19937 generator(randomDevice());
@ -161,7 +152,7 @@ void AvatarMixer::broadcastAvatarData() {
// reset packet pointers for this node // reset packet pointers for this node
mixedAvatarByteArray.resize(numPacketHeaderBytes); mixedAvatarByteArray.resize(numPacketHeaderBytes);
AvatarData& avatar = nodeData->getAvatar(); AvatarData& avatar = nodeData->getAvatar();
glm::vec3 myPosition = avatar.getPosition(); glm::vec3 myPosition = avatar.getPosition();
@ -179,7 +170,13 @@ void AvatarMixer::broadcastAvatarData() {
// keep track of outbound data rate specifically for avatar data // keep track of outbound data rate specifically for avatar data
int numAvatarDataBytes = 0; int numAvatarDataBytes = 0;
// keep track of the number of other avatars held back in this frame
int numAvatarsHeldBack = 0;
// keep track of the number of other avatar frames skipped
int numAvatarsWithSkippedFrames = 0;
// use the data rate specifically for avatar data for FRD adjustment checks // use the data rate specifically for avatar data for FRD adjustment checks
float avatarDataRateLastSecond = nodeData->getOutboundAvatarDataKbps(); float avatarDataRateLastSecond = nodeData->getOutboundAvatarDataKbps();
@ -257,8 +254,38 @@ void AvatarMixer::broadcastAvatarData() {
&& distribution(generator) > (nodeData->getFullRateDistance() / distanceToAvatar)) { && distribution(generator) > (nodeData->getFullRateDistance() / distanceToAvatar)) {
return; return;
} }
PacketSequenceNumber lastSeqToReceiver = nodeData->getLastBroadcastSequenceNumber(otherNode->getUUID());
PacketSequenceNumber lastSeqFromSender = otherNode->getLastSequenceNumberForPacketType(PacketTypeAvatarData);
if (lastSeqToReceiver > lastSeqFromSender) {
// Did we somehow get out of order packets from the sender?
// We don't expect this to happen - in RELEASE we add this to a trackable stat
// and in DEBUG we crash on the assert
otherNodeData->incrementNumOutOfOrderSends();
assert(false);
}
// make sure we haven't already sent this data from this sender to this receiver
// or that somehow we haven't sent
if (lastSeqToReceiver == lastSeqFromSender && lastSeqToReceiver != 0) {
++numAvatarsHeldBack;
return;
} else if (lastSeqFromSender - lastSeqToReceiver > 1) {
// this is a skip - we still send the packet but capture the presence of the skip so we see it happening
++numAvatarsWithSkippedFrames;
}
// we're going to send this avatar
// increment the number of avatars sent to this reciever
nodeData->incrementNumAvatarsSentLastFrame(); nodeData->incrementNumAvatarsSentLastFrame();
// set the last sent sequence number for this sender on the receiver
nodeData->setLastBroadcastSequenceNumber(otherNode->getUUID(),
otherNode->getLastSequenceNumberForPacketType(PacketTypeAvatarData));
QByteArray avatarByteArray; QByteArray avatarByteArray;
avatarByteArray.append(otherNode->getUUID().toRfc4122()); avatarByteArray.append(otherNode->getUUID().toRfc4122());
@ -287,7 +314,7 @@ void AvatarMixer::broadcastAvatarData() {
&& (forceSend && (forceSend
|| otherNodeData->getBillboardChangeTimestamp() > _lastFrameTimestamp || otherNodeData->getBillboardChangeTimestamp() > _lastFrameTimestamp
|| randFloat() < BILLBOARD_AND_IDENTITY_SEND_PROBABILITY)) { || randFloat() < BILLBOARD_AND_IDENTITY_SEND_PROBABILITY)) {
QByteArray billboardPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarBillboard); QByteArray billboardPacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeAvatarBillboard);
billboardPacket.append(otherNode->getUUID().toRfc4122()); billboardPacket.append(otherNode->getUUID().toRfc4122());
billboardPacket.append(otherNodeData->getAvatar().getBillboard()); billboardPacket.append(otherNodeData->getAvatar().getBillboard());
@ -301,7 +328,7 @@ void AvatarMixer::broadcastAvatarData() {
|| otherNodeData->getIdentityChangeTimestamp() > _lastFrameTimestamp || otherNodeData->getIdentityChangeTimestamp() > _lastFrameTimestamp
|| randFloat() < BILLBOARD_AND_IDENTITY_SEND_PROBABILITY)) { || randFloat() < BILLBOARD_AND_IDENTITY_SEND_PROBABILITY)) {
QByteArray identityPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarIdentity); QByteArray identityPacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeAvatarIdentity);
QByteArray individualData = otherNodeData->getAvatar().identityByteArray(); QByteArray individualData = otherNodeData->getAvatar().identityByteArray();
individualData.replace(0, NUM_BYTES_RFC4122_UUID, otherNode->getUUID().toRfc4122()); individualData.replace(0, NUM_BYTES_RFC4122_UUID, otherNode->getUUID().toRfc4122());
@ -318,6 +345,10 @@ void AvatarMixer::broadcastAvatarData() {
// record the bytes sent for other avatar data in the AvatarMixerClientData // record the bytes sent for other avatar data in the AvatarMixerClientData
nodeData->recordSentAvatarData(numAvatarDataBytes + mixedAvatarByteArray.size()); nodeData->recordSentAvatarData(numAvatarDataBytes + mixedAvatarByteArray.size());
// record the number of avatars held back this frame
nodeData->recordNumOtherAvatarStarves(numAvatarsHeldBack);
nodeData->recordNumOtherAvatarSkips(numAvatarsWithSkippedFrames);
if (numOtherAvatars == 0) { if (numOtherAvatars == 0) {
// update the full rate distance to FLOAT_MAX since we didn't have any other avatars to send // update the full rate distance to FLOAT_MAX since we didn't have any other avatars to send
@ -334,13 +365,36 @@ void AvatarMixer::broadcastAvatarData() {
void AvatarMixer::nodeKilled(SharedNodePointer killedNode) { void AvatarMixer::nodeKilled(SharedNodePointer killedNode) {
if (killedNode->getType() == NodeType::Agent if (killedNode->getType() == NodeType::Agent
&& killedNode->getLinkedData()) { && killedNode->getLinkedData()) {
auto nodeList = DependencyManager::get<NodeList>();
// this was an avatar we were sending to other people // this was an avatar we were sending to other people
// send a kill packet for it to our other nodes // send a kill packet for it to our other nodes
QByteArray killPacket = byteArrayWithPopulatedHeader(PacketTypeKillAvatar); QByteArray killPacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeKillAvatar);
killPacket += killedNode->getUUID().toRfc4122(); killPacket += killedNode->getUUID().toRfc4122();
DependencyManager::get<NodeList>()->broadcastToNodes(killPacket, nodeList->broadcastToNodes(killPacket, NodeSet() << NodeType::Agent);
NodeSet() << NodeType::Agent);
// we also want to remove sequence number data for this avatar on our other avatars
// so invoke the appropriate method on the AvatarMixerClientData for other avatars
nodeList->eachMatchingNode(
[&](const SharedNodePointer& node)->bool {
if (!node->getLinkedData()) {
return false;
}
if (node->getUUID() == killedNode->getUUID()) {
return false;
}
return true;
},
[&](const SharedNodePointer& node) {
QMetaObject::invokeMethod(node->getLinkedData(),
"removeLastBroadcastSequenceNumber",
Qt::AutoConnection,
Q_ARG(const QUuid&, QUuid(killedNode->getUUID())));
}
);
} }
} }
@ -430,11 +484,14 @@ void AvatarMixer::sendStatsPacket() {
AvatarMixerClientData* clientData = static_cast<AvatarMixerClientData*>(node->getLinkedData()); AvatarMixerClientData* clientData = static_cast<AvatarMixerClientData*>(node->getLinkedData());
if (clientData) { if (clientData) {
clientData->loadJSONStats(avatarStats); MutexTryLocker lock(clientData->getMutex());
if (lock.isLocked()) {
clientData->loadJSONStats(avatarStats);
// add the diff between the full outbound bandwidth and the measured bandwidth for AvatarData send only // add the diff between the full outbound bandwidth and the measured bandwidth for AvatarData send only
avatarStats["delta_full_vs_avatar_data_kbps"] = avatarStats["delta_full_vs_avatar_data_kbps"] =
avatarStats[NODE_OUTBOUND_KBPS_STAT_KEY].toDouble() - avatarStats[OUTBOUND_AVATAR_DATA_STATS_KEY].toDouble(); avatarStats[NODE_OUTBOUND_KBPS_STAT_KEY].toDouble() - avatarStats[OUTBOUND_AVATAR_DATA_STATS_KEY].toDouble();
}
} }
avatarsObject[uuidStringWithoutCurlyBraces(node->getUUID())] = avatarStats; avatarsObject[uuidStringWithoutCurlyBraces(node->getUUID())] = avatarStats;
@ -455,7 +512,9 @@ void AvatarMixer::run() {
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
nodeList->addNodeTypeToInterestSet(NodeType::Agent); nodeList->addNodeTypeToInterestSet(NodeType::Agent);
nodeList->linkedDataCreateCallback = attachAvatarDataToNode; nodeList->linkedDataCreateCallback = [] (Node* node) {
node->setLinkedData(new AvatarMixerClientData());
};
// setup the timer that will be fired on the broadcast thread // setup the timer that will be fired on the broadcast thread
_broadcastTimer = new QTimer(); _broadcastTimer = new QTimer();

View file

@ -25,11 +25,24 @@ bool AvatarMixerClientData::checkAndSetHasReceivedFirstPackets() {
return oldValue; return oldValue;
} }
PacketSequenceNumber AvatarMixerClientData::getLastBroadcastSequenceNumber(const QUuid& nodeUUID) const {
// return the matching PacketSequenceNumber, or the default if we don't have it
auto nodeMatch = _lastBroadcastSequenceNumbers.find(nodeUUID);
if (nodeMatch != _lastBroadcastSequenceNumbers.end()) {
return nodeMatch->second;
} else {
return DEFAULT_SEQUENCE_NUMBER;
}
}
void AvatarMixerClientData::loadJSONStats(QJsonObject& jsonObject) const { void AvatarMixerClientData::loadJSONStats(QJsonObject& jsonObject) const {
jsonObject["display_name"] = _avatar.getDisplayName(); jsonObject["display_name"] = _avatar.getDisplayName();
jsonObject["full_rate_distance"] = _fullRateDistance; jsonObject["full_rate_distance"] = _fullRateDistance;
jsonObject["max_avatar_distance"] = _maxAvatarDistance; jsonObject["max_avatar_distance"] = _maxAvatarDistance;
jsonObject["num_avatars_sent_last_frame"] = _numAvatarsSentLastFrame; jsonObject["num_avatars_sent_last_frame"] = _numAvatarsSentLastFrame;
jsonObject["avg_other_avatar_starves_per_second"] = getAvgNumOtherAvatarStarvesPerSecond();
jsonObject["avg_other_avatar_skips_per_second"] = getAvgNumOtherAvatarSkipsPerSecond();
jsonObject["total_num_out_of_order_sends"] = _numOutOfOrderSends;
jsonObject[OUTBOUND_AVATAR_DATA_STATS_KEY] = getOutboundAvatarDataKbps(); jsonObject[OUTBOUND_AVATAR_DATA_STATS_KEY] = getOutboundAvatarDataKbps();
} }

View file

@ -14,6 +14,7 @@
#include <algorithm> #include <algorithm>
#include <cfloat> #include <cfloat>
#include <unordered_map>
#include <QtCore/QJsonObject> #include <QtCore/QJsonObject>
#include <QtCore/QUrl> #include <QtCore/QUrl>
@ -21,7 +22,9 @@
#include <AvatarData.h> #include <AvatarData.h>
#include <NodeData.h> #include <NodeData.h>
#include <NumericalConstants.h> #include <NumericalConstants.h>
#include <PacketHeaders.h>
#include <SimpleMovingAverage.h> #include <SimpleMovingAverage.h>
#include <UUIDHasher.h>
const QString OUTBOUND_AVATAR_DATA_STATS_KEY = "outbound_av_data_kbps"; const QString OUTBOUND_AVATAR_DATA_STATS_KEY = "outbound_av_data_kbps";
@ -32,7 +35,12 @@ public:
AvatarData& getAvatar() { return _avatar; } AvatarData& getAvatar() { return _avatar; }
bool checkAndSetHasReceivedFirstPackets(); bool checkAndSetHasReceivedFirstPackets();
PacketSequenceNumber getLastBroadcastSequenceNumber(const QUuid& nodeUUID) const;
void setLastBroadcastSequenceNumber(const QUuid& nodeUUID, PacketSequenceNumber sequenceNumber)
{ _lastBroadcastSequenceNumbers[nodeUUID] = sequenceNumber; }
Q_INVOKABLE void removeLastBroadcastSequenceNumber(const QUuid& nodeUUID) { _lastBroadcastSequenceNumbers.erase(nodeUUID); }
quint64 getBillboardChangeTimestamp() const { return _billboardChangeTimestamp; } quint64 getBillboardChangeTimestamp() const { return _billboardChangeTimestamp; }
void setBillboardChangeTimestamp(quint64 billboardChangeTimestamp) { _billboardChangeTimestamp = billboardChangeTimestamp; } void setBillboardChangeTimestamp(quint64 billboardChangeTimestamp) { _billboardChangeTimestamp = billboardChangeTimestamp; }
@ -49,6 +57,14 @@ public:
void incrementNumAvatarsSentLastFrame() { ++_numAvatarsSentLastFrame; } void incrementNumAvatarsSentLastFrame() { ++_numAvatarsSentLastFrame; }
int getNumAvatarsSentLastFrame() const { return _numAvatarsSentLastFrame; } int getNumAvatarsSentLastFrame() const { return _numAvatarsSentLastFrame; }
void recordNumOtherAvatarStarves(int numAvatarsHeldBack) { _otherAvatarStarves.updateAverage((float) numAvatarsHeldBack); }
float getAvgNumOtherAvatarStarvesPerSecond() const { return _otherAvatarStarves.getAverageSampleValuePerSecond(); }
void recordNumOtherAvatarSkips(int numOtherAvatarSkips) { _otherAvatarSkips.updateAverage((float) numOtherAvatarSkips); }
float getAvgNumOtherAvatarSkipsPerSecond() const { return _otherAvatarSkips.getAverageSampleValuePerSecond(); }
void incrementNumOutOfOrderSends() { ++_numOutOfOrderSends; }
int getNumFramesSinceFRDAdjustment() const { return _numFramesSinceAdjustment; } int getNumFramesSinceFRDAdjustment() const { return _numFramesSinceAdjustment; }
void incrementNumFramesSinceFRDAdjustment() { ++_numFramesSinceAdjustment; } void incrementNumFramesSinceFRDAdjustment() { ++_numFramesSinceAdjustment; }
void resetNumFramesSinceFRDAdjustment() { _numFramesSinceAdjustment = 0; } void resetNumFramesSinceFRDAdjustment() { _numFramesSinceAdjustment = 0; }
@ -61,13 +77,23 @@ public:
void loadJSONStats(QJsonObject& jsonObject) const; void loadJSONStats(QJsonObject& jsonObject) const;
private: private:
AvatarData _avatar; AvatarData _avatar;
std::unordered_map<QUuid, PacketSequenceNumber, UUIDHasher> _lastBroadcastSequenceNumbers;
bool _hasReceivedFirstPackets = false; bool _hasReceivedFirstPackets = false;
quint64 _billboardChangeTimestamp = 0; quint64 _billboardChangeTimestamp = 0;
quint64 _identityChangeTimestamp = 0; quint64 _identityChangeTimestamp = 0;
float _fullRateDistance = FLT_MAX; float _fullRateDistance = FLT_MAX;
float _maxAvatarDistance = FLT_MAX; float _maxAvatarDistance = FLT_MAX;
int _numAvatarsSentLastFrame = 0; int _numAvatarsSentLastFrame = 0;
int _numFramesSinceAdjustment = 0; int _numFramesSinceAdjustment = 0;
SimpleMovingAverage _otherAvatarStarves;
SimpleMovingAverage _otherAvatarSkips;
int _numOutOfOrderSends = 0;
SimpleMovingAverage _avgOtherAvatarDataRate; SimpleMovingAverage _avgOtherAvatarDataRate;
}; };

View file

@ -64,7 +64,9 @@ void EntityServer::entityCreated(const EntityItem& newEntity, const SharedNodePo
unsigned char outputBuffer[MAX_PACKET_SIZE]; unsigned char outputBuffer[MAX_PACKET_SIZE];
unsigned char* copyAt = outputBuffer; unsigned char* copyAt = outputBuffer;
int numBytesPacketHeader = populatePacketHeader(reinterpret_cast<char*>(outputBuffer), PacketTypeEntityAddResponse); auto nodeList = DependencyManager::get<NodeList>();
int numBytesPacketHeader = nodeList->populatePacketHeader(reinterpret_cast<char*>(outputBuffer), PacketTypeEntityAddResponse);
int packetLength = numBytesPacketHeader; int packetLength = numBytesPacketHeader;
copyAt += numBytesPacketHeader; copyAt += numBytesPacketHeader;
@ -81,7 +83,7 @@ void EntityServer::entityCreated(const EntityItem& newEntity, const SharedNodePo
copyAt += sizeof(entityID); copyAt += sizeof(entityID);
packetLength += sizeof(entityID); packetLength += sizeof(entityID);
DependencyManager::get<NodeList>()->writeDatagram((char*) outputBuffer, packetLength, senderNode); nodeList->writeDatagram((char*) outputBuffer, packetLength, senderNode);
} }

View file

@ -277,9 +277,11 @@ int OctreeInboundPacketProcessor::sendNackPackets() {
char* dataAt = packet; char* dataAt = packet;
int bytesRemaining = MAX_PACKET_SIZE; int bytesRemaining = MAX_PACKET_SIZE;
auto nodeList = DependencyManager::get<NodeList>();
// pack header // pack header
int numBytesPacketHeader = populatePacketHeader(packet, _myServer->getMyEditNackType()); int numBytesPacketHeader = nodeList->populatePacketHeader(packet, _myServer->getMyEditNackType());
dataAt += numBytesPacketHeader; dataAt += numBytesPacketHeader;
bytesRemaining -= numBytesPacketHeader; bytesRemaining -= numBytesPacketHeader;
@ -301,7 +303,7 @@ int OctreeInboundPacketProcessor::sendNackPackets() {
numSequenceNumbersAvailable -= numSequenceNumbers; numSequenceNumbersAvailable -= numSequenceNumbers;
// send it // send it
DependencyManager::get<NodeList>()->writeUnverifiedDatagram(packet, dataAt - packet, destinationNode); nodeList->writeUnverifiedDatagram(packet, dataAt - packet, destinationNode);
packetsSent++; packetsSent++;
qDebug() << "NACK Sent back to editor/client... destinationNode=" << nodeUUID; qDebug() << "NACK Sent back to editor/client... destinationNode=" << nodeUUID;

View file

@ -189,7 +189,9 @@ void OctreeQueryNode::resetOctreePacket() {
} }
_octreePacketAvailableBytes = MAX_PACKET_SIZE; _octreePacketAvailableBytes = MAX_PACKET_SIZE;
int numBytesPacketHeader = populatePacketHeader(reinterpret_cast<char*>(_octreePacket), _myPacketType); int numBytesPacketHeader = DependencyManager::get<NodeList>()->populatePacketHeader(reinterpret_cast<char*>(_octreePacket),
_myPacketType);
_octreePacketAt = _octreePacket + numBytesPacketHeader; _octreePacketAt = _octreePacket + numBytesPacketHeader;
_octreePacketAvailableBytes -= numBytesPacketHeader; _octreePacketAvailableBytes -= numBytesPacketHeader;

View file

@ -213,14 +213,6 @@ void OctreeServer::trackProcessWaitTime(float time) {
_averageProcessWaitTime.updateAverage(time); _averageProcessWaitTime.updateAverage(time);
} }
void OctreeServer::attachQueryNodeToNode(Node* newNode) {
if (!newNode->getLinkedData() && _instance) {
OctreeQueryNode* newQueryNodeData = _instance->createOctreeQueryNode();
newQueryNodeData->init();
newNode->setLinkedData(newQueryNodeData);
}
}
OctreeServer::OctreeServer(const QByteArray& packet) : OctreeServer::OctreeServer(const QByteArray& packet) :
ThreadedAssignment(packet), ThreadedAssignment(packet),
_argc(0), _argc(0),
@ -1132,7 +1124,11 @@ void OctreeServer::run() {
setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(stdout, NULL, _IOLBF, 0);
#endif #endif
nodeList->linkedDataCreateCallback = &OctreeServer::attachQueryNodeToNode; nodeList->linkedDataCreateCallback = [] (Node* node) {
OctreeQueryNode* newQueryNodeData = _instance->createOctreeQueryNode();
newQueryNodeData->init();
node->setLinkedData(newQueryNodeData);
};
srand((unsigned)time(0)); srand((unsigned)time(0));

View file

@ -75,8 +75,6 @@ public:
virtual bool hasSpecialPacketToSend(const SharedNodePointer& node) { return false; } virtual bool hasSpecialPacketToSend(const SharedNodePointer& node) { return false; }
virtual int sendSpecialPacket(const SharedNodePointer& node, OctreeQueryNode* queryNode, int& packetsSent) { return 0; } virtual int sendSpecialPacket(const SharedNodePointer& node, OctreeQueryNode* queryNode, int& packetsSent) { return 0; }
static void attachQueryNodeToNode(Node* newNode);
static float SKIP_TIME; // use this for trackXXXTime() calls for non-times static float SKIP_TIME; // use this for trackXXXTime() calls for non-times
static void trackLoopTime(float time) { _averageLoopTime.updateAverage(time); } static void trackLoopTime(float time) { _averageLoopTime.updateAverage(time); }

View file

@ -619,10 +619,12 @@ void DomainServer::handleConnectRequest(const QByteArray& packet, const HifiSock
packetStream >> nodeInterestList >> username >> usernameSignature; packetStream >> nodeInterestList >> username >> usernameSignature;
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
QString reason; QString reason;
if (!isAssignment && !shouldAllowConnectionFromNode(username, usernameSignature, senderSockAddr, reason)) { if (!isAssignment && !shouldAllowConnectionFromNode(username, usernameSignature, senderSockAddr, reason)) {
// this is an agent and we've decided we won't let them connect - send them a packet to deny connection // this is an agent and we've decided we won't let them connect - send them a packet to deny connection
QByteArray connectionDeniedByteArray = byteArrayWithPopulatedHeader(PacketTypeDomainConnectionDenied); QByteArray connectionDeniedByteArray = limitedNodeList->byteArrayWithPopulatedHeader(PacketTypeDomainConnectionDenied);
QDataStream out(&connectionDeniedByteArray, QIODevice::WriteOnly | QIODevice::Append); QDataStream out(&connectionDeniedByteArray, QIODevice::WriteOnly | QIODevice::Append);
out << reason; out << reason;
// tell client it has been refused. // tell client it has been refused.
@ -664,10 +666,9 @@ void DomainServer::handleConnectRequest(const QByteArray& packet, const HifiSock
canRez = canAdjustLocks; canRez = canAdjustLocks;
} }
SharedNodePointer newNode = SharedNodePointer newNode = limitedNodeList->addOrUpdateNode(nodeUUID, nodeType,
DependencyManager::get<LimitedNodeList>()->addOrUpdateNode(nodeUUID, nodeType, publicSockAddr, localSockAddr,
publicSockAddr, localSockAddr, canAdjustLocks, canRez);
canAdjustLocks, canRez);
// when the newNode is created the linked data is also created // when the newNode is created the linked data is also created
// if this was a static assignment set the UUID, set the sendingSockAddr // if this was a static assignment set the UUID, set the sendingSockAddr
DomainServerNodeData* nodeData = reinterpret_cast<DomainServerNodeData*>(newNode->getLinkedData()); DomainServerNodeData* nodeData = reinterpret_cast<DomainServerNodeData*>(newNode->getLinkedData());
@ -926,8 +927,8 @@ NodeSet DomainServer::nodeInterestListFromPacket(const QByteArray& packet, int n
void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const HifiSockAddr &senderSockAddr, void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const HifiSockAddr &senderSockAddr,
const NodeSet& nodeInterestList) { const NodeSet& nodeInterestList) {
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
QByteArray broadcastPacket = byteArrayWithPopulatedHeader(PacketTypeDomainList); QByteArray broadcastPacket = limitedNodeList->byteArrayWithPopulatedHeader(PacketTypeDomainList);
// always send the node their own UUID back // always send the node their own UUID back
QDataStream broadcastDataStream(&broadcastPacket, QIODevice::Append); QDataStream broadcastDataStream(&broadcastPacket, QIODevice::Append);
@ -939,8 +940,6 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
DomainServerNodeData* nodeData = reinterpret_cast<DomainServerNodeData*>(node->getLinkedData()); DomainServerNodeData* nodeData = reinterpret_cast<DomainServerNodeData*>(node->getLinkedData());
auto nodeList = DependencyManager::get<LimitedNodeList>();
// if we've established a connection via ICE with this peer, use that socket // if we've established a connection via ICE with this peer, use that socket
// otherwise just try to reply back to them on their sending socket (although that may not work) // otherwise just try to reply back to them on their sending socket (although that may not work)
HifiSockAddr destinationSockAddr = _connectedICEPeers.value(node->getUUID()); HifiSockAddr destinationSockAddr = _connectedICEPeers.value(node->getUUID());
@ -955,7 +954,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
if (nodeData->isAuthenticated()) { if (nodeData->isAuthenticated()) {
// if this authenticated node has any interest types, send back those nodes as well // if this authenticated node has any interest types, send back those nodes as well
nodeList->eachNode([&](const SharedNodePointer& otherNode){ limitedNodeList->eachNode([&](const SharedNodePointer& otherNode){
// reset our nodeByteArray and nodeDataStream // reset our nodeByteArray and nodeDataStream
QByteArray nodeByteArray; QByteArray nodeByteArray;
QDataStream nodeDataStream(&nodeByteArray, QIODevice::Append); QDataStream nodeDataStream(&nodeByteArray, QIODevice::Append);
@ -986,7 +985,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
// we need to break here and start a new packet // we need to break here and start a new packet
// so send the current one // so send the current one
nodeList->writeDatagram(broadcastPacket, node, senderSockAddr); limitedNodeList->writeUnverifiedDatagram(broadcastPacket, node, senderSockAddr);
// reset the broadcastPacket structure // reset the broadcastPacket structure
broadcastPacket.resize(numBroadcastPacketLeadBytes); broadcastPacket.resize(numBroadcastPacketLeadBytes);
@ -999,26 +998,26 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
}); });
} }
} }
// always write the last broadcastPacket // always write the last broadcastPacket
nodeList->writeDatagram(broadcastPacket, node, senderSockAddr); limitedNodeList->writeUnverifiedDatagram(broadcastPacket, node, senderSockAddr);
} }
void DomainServer::readAvailableDatagrams() { void DomainServer::readAvailableDatagrams() {
auto nodeList = DependencyManager::get<LimitedNodeList>(); auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
HifiSockAddr senderSockAddr; HifiSockAddr senderSockAddr;
QByteArray receivedPacket; QByteArray receivedPacket;
static QByteArray assignmentPacket = byteArrayWithPopulatedHeader(PacketTypeCreateAssignment); static QByteArray assignmentPacket = limitedNodeList->byteArrayWithPopulatedHeader(PacketTypeCreateAssignment);
static int numAssignmentPacketHeaderBytes = assignmentPacket.size(); static int numAssignmentPacketHeaderBytes = assignmentPacket.size();
while (nodeList->getNodeSocket().hasPendingDatagrams()) { while (limitedNodeList->getNodeSocket().hasPendingDatagrams()) {
receivedPacket.resize(nodeList->getNodeSocket().pendingDatagramSize()); receivedPacket.resize(limitedNodeList->getNodeSocket().pendingDatagramSize());
nodeList->getNodeSocket().readDatagram(receivedPacket.data(), receivedPacket.size(), limitedNodeList->getNodeSocket().readDatagram(receivedPacket.data(), receivedPacket.size(),
senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer()); senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer());
if (packetTypeForPacket(receivedPacket) == PacketTypeRequestAssignment if (packetTypeForPacket(receivedPacket) == PacketTypeRequestAssignment
&& nodeList->packetVersionAndHashMatch(receivedPacket)) { && limitedNodeList->packetVersionAndHashMatch(receivedPacket)) {
// construct the requested assignment from the packet data // construct the requested assignment from the packet data
Assignment requestAssignment(receivedPacket); Assignment requestAssignment(receivedPacket);
@ -1059,7 +1058,7 @@ void DomainServer::readAvailableDatagrams() {
assignmentStream << uniqueAssignment; assignmentStream << uniqueAssignment;
nodeList->getNodeSocket().writeDatagram(assignmentPacket, limitedNodeList->getNodeSocket().writeDatagram(assignmentPacket,
senderSockAddr.getAddress(), senderSockAddr.getPort()); senderSockAddr.getAddress(), senderSockAddr.getPort());
// add the information for that deployed assignment to the hash of pending assigned nodes // add the information for that deployed assignment to the hash of pending assigned nodes
@ -1081,16 +1080,16 @@ void DomainServer::readAvailableDatagrams() {
processDatagram(receivedPacket, senderSockAddr); processDatagram(receivedPacket, senderSockAddr);
} else { } else {
// we're using DTLS, so tell the sender to get back to us using DTLS // we're using DTLS, so tell the sender to get back to us using DTLS
static QByteArray dtlsRequiredPacket = byteArrayWithPopulatedHeader(PacketTypeDomainServerRequireDTLS); static QByteArray dtlsRequiredPacket = limitedNodeList->byteArrayWithPopulatedHeader(PacketTypeDomainServerRequireDTLS);
static int numBytesDTLSHeader = numBytesForPacketHeaderGivenPacketType(PacketTypeDomainServerRequireDTLS); static int numBytesDTLSHeader = numBytesForPacketHeaderGivenPacketType(PacketTypeDomainServerRequireDTLS);
if (dtlsRequiredPacket.size() == numBytesDTLSHeader) { if (dtlsRequiredPacket.size() == numBytesDTLSHeader) {
// pack the port that we accept DTLS traffic on // pack the port that we accept DTLS traffic on
unsigned short dtlsPort = nodeList->getDTLSSocket().localPort(); unsigned short dtlsPort = limitedNodeList->getDTLSSocket().localPort();
dtlsRequiredPacket.replace(numBytesDTLSHeader, sizeof(dtlsPort), reinterpret_cast<const char*>(&dtlsPort)); dtlsRequiredPacket.replace(numBytesDTLSHeader, sizeof(dtlsPort), reinterpret_cast<const char*>(&dtlsPort));
} }
nodeList->writeUnverifiedDatagram(dtlsRequiredPacket, senderSockAddr); limitedNodeList->writeUnverifiedDatagram(dtlsRequiredPacket, senderSockAddr);
} }
} }
} }

View file

@ -117,7 +117,7 @@ void IceServer::sendHeartbeatResponse(const HifiSockAddr& destinationSockAddr, Q
QSet<QUuid>::iterator peerID = connections.begin(); QSet<QUuid>::iterator peerID = connections.begin();
QByteArray outgoingPacket(MAX_PACKET_SIZE, 0); QByteArray outgoingPacket(MAX_PACKET_SIZE, 0);
int currentPacketSize = populatePacketHeader(outgoingPacket, PacketTypeIceServerHeartbeatResponse, _id); int currentPacketSize = populatePacketHeaderWithUUID(outgoingPacket, PacketTypeIceServerHeartbeatResponse, _id);
int numHeaderBytes = currentPacketSize; int numHeaderBytes = currentPacketSize;
// go through the connections, sending packets containing connection information for those nodes // go through the connections, sending packets containing connection information for those nodes
@ -136,7 +136,7 @@ void IceServer::sendHeartbeatResponse(const HifiSockAddr& destinationSockAddr, Q
destinationSockAddr.getAddress(), destinationSockAddr.getPort()); destinationSockAddr.getAddress(), destinationSockAddr.getPort());
// reset the packet size to our number of header bytes // reset the packet size to our number of header bytes
currentPacketSize = populatePacketHeader(outgoingPacket, PacketTypeIceServerHeartbeatResponse, _id); currentPacketSize = populatePacketHeaderWithUUID(outgoingPacket, PacketTypeIceServerHeartbeatResponse, _id);
} }
// append the current peer bytes // append the current peer bytes

View file

@ -2577,7 +2577,7 @@ int Application::sendNackPackets() {
int bytesRemaining = MAX_PACKET_SIZE; int bytesRemaining = MAX_PACKET_SIZE;
// pack header // pack header
int numBytesPacketHeader = populatePacketHeader(packet, PacketTypeOctreeDataNack); int numBytesPacketHeader = nodeList->populatePacketHeader(packet, PacketTypeOctreeDataNack);
dataAt += numBytesPacketHeader; dataAt += numBytesPacketHeader;
bytesRemaining -= numBytesPacketHeader; bytesRemaining -= numBytesPacketHeader;
@ -2778,7 +2778,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
unsigned char* endOfQueryPacket = queryPacket; unsigned char* endOfQueryPacket = queryPacket;
// insert packet type/version and node UUID // insert packet type/version and node UUID
endOfQueryPacket += populatePacketHeader(reinterpret_cast<char*>(endOfQueryPacket), packetType); endOfQueryPacket += nodeList->populatePacketHeader(reinterpret_cast<char*>(endOfQueryPacket), packetType);
// encode the query data... // encode the query data...
endOfQueryPacket += _octreeQuery.getBroadcastData(endOfQueryPacket); endOfQueryPacket += _octreeQuery.getBroadcastData(endOfQueryPacket);

View file

@ -847,8 +847,9 @@ int MyAvatar::parseDataAtOffset(const QByteArray& packet, int offset) {
} }
void MyAvatar::sendKillAvatar() { void MyAvatar::sendKillAvatar() {
QByteArray killPacket = byteArrayWithPopulatedHeader(PacketTypeKillAvatar); auto nodeList = DependencyManager::get<NodeList>();
DependencyManager::get<NodeList>()->broadcastToNodes(killPacket, NodeSet() << NodeType::AvatarMixer); QByteArray killPacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeKillAvatar);
nodeList->broadcastToNodes(killPacket, NodeSet() << NodeType::AvatarMixer);
} }
void MyAvatar::updateLookAtTargetAvatar() { void MyAvatar::updateLookAtTargetAvatar() {

View file

@ -889,15 +889,9 @@ void ApplicationOverlay::renderAudioMeter() {
} }
bool isClipping = ((audio->getTimeSinceLastClip() > 0.0f) && (audio->getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME)); bool isClipping = ((audio->getTimeSinceLastClip() > 0.0f) && (audio->getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME));
auto canvasSize = qApp->getCanvasSize();
if ((audio->getTimeSinceLastClip() > 0.0f) && (audio->getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME)) {
const float MAX_MAGNITUDE = 0.7f;
float magnitude = MAX_MAGNITUDE * (1 - audio->getTimeSinceLastClip() / CLIPPING_INDICATOR_TIME);
renderCollisionOverlay(canvasSize.x, canvasSize.y, magnitude, 1.0f);
}
DependencyManager::get<AudioToolBox>()->render(MIRROR_VIEW_LEFT_PADDING + AUDIO_METER_GAP, audioMeterY, cameraSpace, boxed); DependencyManager::get<AudioToolBox>()->render(MIRROR_VIEW_LEFT_PADDING + AUDIO_METER_GAP, audioMeterY, cameraSpace, boxed);
auto canvasSize = qApp->getCanvasSize();
DependencyManager::get<AudioScope>()->render(canvasSize.x, canvasSize.y); DependencyManager::get<AudioScope>()->render(canvasSize.x, canvasSize.y);
DependencyManager::get<AudioIOStatsRenderer>()->render(WHITE_TEXT, canvasSize.x, canvasSize.y); DependencyManager::get<AudioIOStatsRenderer>()->render(WHITE_TEXT, canvasSize.x, canvasSize.y);

View file

@ -837,7 +837,7 @@ void AudioClient::handleAudioInput() {
} }
} }
char* currentPacketPtr = audioDataPacket + populatePacketHeader(audioDataPacket, packetType); char* currentPacketPtr = audioDataPacket + nodeList->populatePacketHeader(audioDataPacket, packetType);
// pack sequence number // pack sequence number
memcpy(currentPacketPtr, &_outgoingAvatarAudioSequenceNumber, sizeof(quint16)); memcpy(currentPacketPtr, &_outgoingAvatarAudioSequenceNumber, sizeof(quint16));
@ -899,7 +899,9 @@ void AudioClient::processReceivedSamples(const QByteArray& inputBuffer, QByteArr
} }
void AudioClient::sendMuteEnvironmentPacket() { void AudioClient::sendMuteEnvironmentPacket() {
QByteArray mutePacket = byteArrayWithPopulatedHeader(PacketTypeMuteEnvironment); auto nodeList = DependencyManager::get<NodeList>();
QByteArray mutePacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeMuteEnvironment);
int headerSize = mutePacket.size(); int headerSize = mutePacket.size();
const float MUTE_RADIUS = 50; const float MUTE_RADIUS = 50;
@ -910,12 +912,11 @@ void AudioClient::sendMuteEnvironmentPacket() {
memcpy(mutePacket.data() + headerSize + sizeof(glm::vec3), &MUTE_RADIUS, sizeof(float)); memcpy(mutePacket.data() + headerSize + sizeof(glm::vec3), &MUTE_RADIUS, sizeof(float));
// grab our audio mixer from the NodeList, if it exists // grab our audio mixer from the NodeList, if it exists
auto nodelist = DependencyManager::get<NodeList>(); SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer);
SharedNodePointer audioMixer = nodelist->soloNodeOfType(NodeType::AudioMixer);
if (audioMixer) { if (audioMixer) {
// send off this mute packet // send off this mute packet
nodelist->writeDatagram(mutePacket, audioMixer); nodeList->writeDatagram(mutePacket, audioMixer);
} }
} }

View file

@ -104,10 +104,12 @@ void AudioIOStats::sendDownstreamAudioStatsPacket() {
// also, call _receivedAudioStream's per-second callback // also, call _receivedAudioStream's per-second callback
_receivedAudioStream->perSecondCallbackForUpdatingStats(); _receivedAudioStream->perSecondCallbackForUpdatingStats();
auto nodeList = DependencyManager::get<NodeList>();
char packet[MAX_PACKET_SIZE]; char packet[MAX_PACKET_SIZE];
// pack header // pack header
int numBytesPacketHeader = populatePacketHeader(packet, PacketTypeAudioStreamStats); int numBytesPacketHeader = nodeList->populatePacketHeader(packet, PacketTypeAudioStreamStats);
char* dataAt = packet + numBytesPacketHeader; char* dataAt = packet + numBytesPacketHeader;
// pack append flag // pack append flag
@ -126,7 +128,6 @@ void AudioIOStats::sendDownstreamAudioStatsPacket() {
dataAt += sizeof(AudioStreamStats); dataAt += sizeof(AudioStreamStats);
// send packet // send packet
auto nodeList = DependencyManager::get<NodeList>();
SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer); SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer);
nodeList->writeDatagram(packet, dataAt - packet, audioMixer); nodeList->writeDatagram(packet, dataAt - packet, audioMixer);
} }

View file

@ -141,11 +141,13 @@ void AudioInjector::injectToMixer() {
_currentSendPosition = 0; _currentSendPosition = 0;
} }
auto nodeList = DependencyManager::get<NodeList>();
// make sure we actually have samples downloaded to inject // make sure we actually have samples downloaded to inject
if (_audioData.size()) { if (_audioData.size()) {
// setup the packet for injected audio // setup the packet for injected audio
QByteArray injectAudioPacket = byteArrayWithPopulatedHeader(PacketTypeInjectAudio); QByteArray injectAudioPacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeInjectAudio);
QDataStream packetStream(&injectAudioPacket, QIODevice::Append); QDataStream packetStream(&injectAudioPacket, QIODevice::Append);
// pack some placeholder sequence number for now // pack some placeholder sequence number for now
@ -226,7 +228,6 @@ void AudioInjector::injectToMixer() {
_audioData.data() + _currentSendPosition, bytesToCopy); _audioData.data() + _currentSendPosition, bytesToCopy);
// grab our audio mixer from the NodeList, if it exists // grab our audio mixer from the NodeList, if it exists
auto nodeList = DependencyManager::get<NodeList>();
SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer); SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer);
// send off this audio packet // send off this audio packet

View file

@ -1077,25 +1077,31 @@ void AvatarData::setJointMappingsFromNetworkReply() {
} }
void AvatarData::sendAvatarDataPacket() { void AvatarData::sendAvatarDataPacket() {
QByteArray dataPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarData); auto nodeList = DependencyManager::get<NodeList>();
QByteArray dataPacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeAvatarData);
dataPacket.append(toByteArray()); dataPacket.append(toByteArray());
DependencyManager::get<NodeList>()->broadcastToNodes(dataPacket, NodeSet() << NodeType::AvatarMixer); nodeList->broadcastToNodes(dataPacket, NodeSet() << NodeType::AvatarMixer);
} }
void AvatarData::sendIdentityPacket() { void AvatarData::sendIdentityPacket() {
QByteArray identityPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarIdentity); auto nodeList = DependencyManager::get<NodeList>();
QByteArray identityPacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeAvatarIdentity);
identityPacket.append(identityByteArray()); identityPacket.append(identityByteArray());
DependencyManager::get<NodeList>()->broadcastToNodes(identityPacket, NodeSet() << NodeType::AvatarMixer); nodeList->broadcastToNodes(identityPacket, NodeSet() << NodeType::AvatarMixer);
} }
void AvatarData::sendBillboardPacket() { void AvatarData::sendBillboardPacket() {
if (!_billboard.isEmpty()) { if (!_billboard.isEmpty()) {
QByteArray billboardPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarBillboard); auto nodeList = DependencyManager::get<NodeList>();
QByteArray billboardPacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeAvatarBillboard);
billboardPacket.append(_billboard); billboardPacket.append(_billboard);
DependencyManager::get<NodeList>()->broadcastToNodes(billboardPacket, NodeSet() << NodeType::AvatarMixer); nodeList->broadcastToNodes(billboardPacket, NodeSet() << NodeType::AvatarMixer);
} }
} }

View file

@ -792,7 +792,8 @@ bool EntityTree::encodeEntitiesDeletedSince(OCTREE_PACKET_SEQUENCE sequenceNumbe
bool hasMoreToSend = true; bool hasMoreToSend = true;
unsigned char* copyAt = outputBuffer; unsigned char* copyAt = outputBuffer;
size_t numBytesPacketHeader = populatePacketHeader(reinterpret_cast<char*>(outputBuffer), PacketTypeEntityErase); size_t numBytesPacketHeader = DependencyManager::get<NodeList>()->populatePacketHeader(reinterpret_cast<char*>(outputBuffer),
PacketTypeEntityErase);
copyAt += numBytesPacketHeader; copyAt += numBytesPacketHeader;
outputLength = numBytesPacketHeader; outputLength = numBytesPacketHeader;

View file

@ -9,6 +9,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include "LimitedNodeList.h"
#include <cstring> #include <cstring>
#include <cstdlib> #include <cstdlib>
#include <cstdio> #include <cstdio>
@ -28,8 +30,6 @@
#include "AccountManager.h" #include "AccountManager.h"
#include "Assignment.h" #include "Assignment.h"
#include "HifiSockAddr.h" #include "HifiSockAddr.h"
#include "LimitedNodeList.h"
#include "PacketHeaders.h"
#include "UUID.h" #include "UUID.h"
#include "NetworkLogging.h" #include "NetworkLogging.h"
@ -230,21 +230,13 @@ qint64 LimitedNodeList::readDatagram(QByteArray& incomingPacket, QHostAddress* a
return result; return result;
} }
qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr, qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr) {
const QUuid& connectionSecret) {
QByteArray datagramCopy = datagram;
if (!connectionSecret.isNull()) {
// setup the MD5 hash for source verification in the header
replaceHashInPacketGivenConnectionUUID(datagramCopy, connectionSecret);
}
// XXX can BandwidthRecorder be used for this? // XXX can BandwidthRecorder be used for this?
// stat collection for packets // stat collection for packets
++_numCollectedPackets; ++_numCollectedPackets;
_numCollectedBytes += datagram.size(); _numCollectedBytes += datagram.size();
qint64 bytesWritten = _nodeSocket.writeDatagram(datagramCopy, qint64 bytesWritten = _nodeSocket.writeDatagram(datagram,
destinationSockAddr.getAddress(), destinationSockAddr.getPort()); destinationSockAddr.getAddress(), destinationSockAddr.getPort());
if (bytesWritten < 0) { if (bytesWritten < 0) {
@ -258,6 +250,12 @@ qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram,
const SharedNodePointer& destinationNode, const SharedNodePointer& destinationNode,
const HifiSockAddr& overridenSockAddr) { const HifiSockAddr& overridenSockAddr) {
if (destinationNode) { if (destinationNode) {
PacketType packetType = packetTypeForPacket(datagram);
if (NON_VERIFIED_PACKETS.contains(packetType)) {
return writeUnverifiedDatagram(datagram, destinationNode, overridenSockAddr);
}
// if we don't have an overridden address, assume they want to send to the node's active socket // if we don't have an overridden address, assume they want to send to the node's active socket
const HifiSockAddr* destinationSockAddr = &overridenSockAddr; const HifiSockAddr* destinationSockAddr = &overridenSockAddr;
if (overridenSockAddr.isNull()) { if (overridenSockAddr.isNull()) {
@ -270,8 +268,26 @@ qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram,
} }
} }
QByteArray datagramCopy = datagram;
// if we're here and the connection secret is null, debug out - this could be a problem
if (destinationNode->getConnectionSecret().isNull()) {
qDebug() << "LimitedNodeList::writeDatagram called for verified datagram with null connection secret for"
<< "destination node" << destinationNode->getUUID() << " - this is either not secure or will cause"
<< "this packet to be unverifiable on the receiving side.";
}
// perform replacement of hash and optionally also sequence number in the header
if (SEQUENCE_NUMBERED_PACKETS.contains(packetType)) {
PacketSequenceNumber sequenceNumber = getNextSequenceNumberForPacket(destinationNode->getUUID(), packetType);
replaceHashAndSequenceNumberInPacket(datagramCopy, destinationNode->getConnectionSecret(),
sequenceNumber, packetType);
} else {
replaceHashInPacket(datagramCopy, destinationNode->getConnectionSecret(), packetType);
}
emit dataSent(destinationNode->getType(), datagram.size()); emit dataSent(destinationNode->getType(), datagram.size());
auto bytesWritten = writeDatagram(datagram, *destinationSockAddr, destinationNode->getConnectionSecret()); auto bytesWritten = writeDatagram(datagramCopy, *destinationSockAddr);
// Keep track of per-destination-node bandwidth // Keep track of per-destination-node bandwidth
destinationNode->recordBytesSent(bytesWritten); destinationNode->recordBytesSent(bytesWritten);
return bytesWritten; return bytesWritten;
@ -296,8 +312,21 @@ qint64 LimitedNodeList::writeUnverifiedDatagram(const QByteArray& datagram, cons
} }
} }
// don't use the node secret! PacketType packetType = packetTypeForPacket(datagram);
return writeDatagram(datagram, *destinationSockAddr, QUuid());
// optionally peform sequence number replacement in the header
if (SEQUENCE_NUMBERED_PACKETS.contains(packetType)) {
QByteArray datagramCopy = datagram;
PacketSequenceNumber sequenceNumber = getNextSequenceNumberForPacket(destinationNode->getUUID(), packetType);
replaceSequenceNumberInPacket(datagramCopy, sequenceNumber, packetType);
// send the datagram with sequence number replaced in header
return writeDatagram(datagramCopy, *destinationSockAddr);
} else {
return writeDatagram(datagram, *destinationSockAddr);
}
} }
// didn't have a destinationNode to send to, return 0 // didn't have a destinationNode to send to, return 0
@ -305,7 +334,7 @@ qint64 LimitedNodeList::writeUnverifiedDatagram(const QByteArray& datagram, cons
} }
qint64 LimitedNodeList::writeUnverifiedDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr) { qint64 LimitedNodeList::writeUnverifiedDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr) {
return writeDatagram(datagram, destinationSockAddr, QUuid()); return writeDatagram(datagram, destinationSockAddr);
} }
qint64 LimitedNodeList::writeDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode, qint64 LimitedNodeList::writeDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode,
@ -318,6 +347,15 @@ qint64 LimitedNodeList::writeUnverifiedDatagram(const char* data, qint64 size, c
return writeUnverifiedDatagram(QByteArray(data, size), destinationNode, overridenSockAddr); return writeUnverifiedDatagram(QByteArray(data, size), destinationNode, overridenSockAddr);
} }
PacketSequenceNumber LimitedNodeList::getNextSequenceNumberForPacket(const QUuid& nodeUUID, PacketType packetType) {
// Thanks to std::map and std::unordered_map this line either default constructs the
// PacketTypeSequenceMap and the PacketSequenceNumber or returns the existing value.
// We use the postfix increment so that the stored value is incremented and the next
// return gives the correct value.
return _packetSequenceNumbers[nodeUUID][packetType]++;
}
void LimitedNodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteArray& packet) { void LimitedNodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteArray& packet) {
// the node decided not to do anything with this packet // the node decided not to do anything with this packet
// if it comes from a known source we should keep that node alive // if it comes from a known source we should keep that node alive
@ -332,6 +370,13 @@ int LimitedNodeList::updateNodeWithDataFromPacket(const SharedNodePointer& match
matchingNode->setLastHeardMicrostamp(usecTimestampNow()); matchingNode->setLastHeardMicrostamp(usecTimestampNow());
// if this was a sequence numbered packet we should store the last seq number for
// a packet of this type for this node
PacketType packetType = packetTypeForPacket(packet);
if (SEQUENCE_NUMBERED_PACKETS.contains(packetType)) {
matchingNode->setLastSequenceNumberForPacketType(sequenceNumberFromHeader(packet, packetType), packetType);
}
NodeData* linkedData = matchingNode->getLinkedData(); NodeData* linkedData = matchingNode->getLinkedData();
if (!linkedData && linkedDataCreateCallback) { if (!linkedData && linkedDataCreateCallback) {
linkedDataCreateCallback(matchingNode.data()); linkedDataCreateCallback(matchingNode.data());
@ -466,8 +511,11 @@ unsigned LimitedNodeList::broadcastToNodes(const QByteArray& packet, const NodeS
} }
QByteArray LimitedNodeList::constructPingPacket(PingType_t pingType, bool isVerified, const QUuid& packetHeaderID) { QByteArray LimitedNodeList::constructPingPacket(PingType_t pingType, bool isVerified, const QUuid& packetHeaderID) {
QByteArray pingPacket = byteArrayWithPopulatedHeader(isVerified ? PacketTypePing : PacketTypeUnverifiedPing,
packetHeaderID); QUuid packetUUID = packetHeaderID.isNull() ? _sessionUUID : packetHeaderID;
QByteArray pingPacket = byteArrayWithUUIDPopulatedHeader(isVerified ? PacketTypePing : PacketTypeUnverifiedPing,
packetUUID);
QDataStream packetStream(&pingPacket, QIODevice::Append); QDataStream packetStream(&pingPacket, QIODevice::Append);
@ -489,8 +537,10 @@ QByteArray LimitedNodeList::constructPingReplyPacket(const QByteArray& pingPacke
PacketType replyType = (packetTypeForPacket(pingPacket) == PacketTypePing) PacketType replyType = (packetTypeForPacket(pingPacket) == PacketTypePing)
? PacketTypePingReply : PacketTypeUnverifiedPingReply; ? PacketTypePingReply : PacketTypeUnverifiedPingReply;
QByteArray replyPacket = byteArrayWithPopulatedHeader(replyType, packetHeaderID); QUuid packetUUID = packetHeaderID.isNull() ? _sessionUUID : packetHeaderID;
QByteArray replyPacket = byteArrayWithUUIDPopulatedHeader(replyType, packetUUID);
QDataStream packetStream(&replyPacket, QIODevice::Append); QDataStream packetStream(&replyPacket, QIODevice::Append);
packetStream << typeFromOriginalPing << timeFromOriginalPing << usecTimestampNow(); packetStream << typeFromOriginalPing << timeFromOriginalPing << usecTimestampNow();
@ -522,11 +572,11 @@ void LimitedNodeList::removeSilentNodes() {
eachNodeHashIterator([&](NodeHash::iterator& it){ eachNodeHashIterator([&](NodeHash::iterator& it){
SharedNodePointer node = it->second; SharedNodePointer node = it->second;
node->getMutex().lock(); node->getMutex().lock();
if ((usecTimestampNow() - node->getLastHeardMicrostamp()) > (NODE_SILENCE_THRESHOLD_MSECS * USECS_PER_MSEC)) { if ((usecTimestampNow() - node->getLastHeardMicrostamp()) > (NODE_SILENCE_THRESHOLD_MSECS * USECS_PER_MSEC)) {
// call the NodeHash erase to get rid of this node // call the NodeHash erase to get rid of this node
it = _nodeHash.unsafe_erase(it); it = _nodeHash.unsafe_erase(it);
killedNodes.insert(node); killedNodes.insert(node);
} else { } else {
// we didn't erase this node, push the iterator forwards // we didn't erase this node, push the iterator forwards
@ -680,7 +730,7 @@ void LimitedNodeList::sendHeartbeatToIceServer(const HifiSockAddr& iceServerSock
headerID = _sessionUUID; headerID = _sessionUUID;
} }
QByteArray iceRequestByteArray = byteArrayWithPopulatedHeader(PacketTypeIceServerHeartbeat, headerID); QByteArray iceRequestByteArray = byteArrayWithUUIDPopulatedHeader(PacketTypeIceServerHeartbeat, headerID);
QDataStream iceDataStream(&iceRequestByteArray, QIODevice::Append); QDataStream iceDataStream(&iceRequestByteArray, QIODevice::Append);
iceDataStream << _publicSockAddr << _localSockAddr; iceDataStream << _publicSockAddr << _localSockAddr;

View file

@ -15,6 +15,7 @@
#include <stdint.h> #include <stdint.h>
#include <iterator> #include <iterator>
#include <memory> #include <memory>
#include <unordered_map>
#ifndef _WIN32 #ifndef _WIN32
#include <unistd.h> // not on windows, not needed for mac or windows #include <unistd.h> // not on windows, not needed for mac or windows
@ -34,6 +35,7 @@
#include "DomainHandler.h" #include "DomainHandler.h"
#include "Node.h" #include "Node.h"
#include "PacketHeaders.h"
#include "UUIDHasher.h" #include "UUIDHasher.h"
const int MAX_PACKET_SIZE = 1450; const int MAX_PACKET_SIZE = 1450;
@ -96,6 +98,13 @@ public:
bool packetVersionAndHashMatch(const QByteArray& packet); bool packetVersionAndHashMatch(const QByteArray& packet);
QByteArray byteArrayWithPopulatedHeader(PacketType packetType)
{ return byteArrayWithUUIDPopulatedHeader(packetType, _sessionUUID); }
int populatePacketHeader(QByteArray& packet, PacketType packetType)
{ return populatePacketHeaderWithUUID(packet, packetType, _sessionUUID); }
int populatePacketHeader(char* packet, PacketType packetType)
{ return populatePacketHeaderWithUUID(packet, packetType, _sessionUUID); }
qint64 readDatagram(QByteArray& incomingPacket, QHostAddress* address, quint16 * port); qint64 readDatagram(QByteArray& incomingPacket, QHostAddress* address, quint16 * port);
qint64 writeDatagram(const QByteArray& datagram, const SharedNodePointer& destinationNode, qint64 writeDatagram(const QByteArray& datagram, const SharedNodePointer& destinationNode,
@ -105,13 +114,14 @@ public:
const HifiSockAddr& overridenSockAddr = HifiSockAddr()); const HifiSockAddr& overridenSockAddr = HifiSockAddr());
qint64 writeUnverifiedDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr); qint64 writeUnverifiedDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr);
qint64 writeDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode, qint64 writeDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode,
const HifiSockAddr& overridenSockAddr = HifiSockAddr()); const HifiSockAddr& overridenSockAddr = HifiSockAddr());
qint64 writeUnverifiedDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode, qint64 writeUnverifiedDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode,
const HifiSockAddr& overridenSockAddr = HifiSockAddr()); const HifiSockAddr& overridenSockAddr = HifiSockAddr());
void(*linkedDataCreateCallback)(Node *); void (*linkedDataCreateCallback)(Node *);
int size() const { return _nodeHash.size(); } int size() const { return _nodeHash.size(); }
@ -224,8 +234,9 @@ protected:
LimitedNodeList(LimitedNodeList const&); // Don't implement, needed to avoid copies of singleton LimitedNodeList(LimitedNodeList const&); // Don't implement, needed to avoid copies of singleton
void operator=(LimitedNodeList const&); // Don't implement, needed to avoid copies of singleton void operator=(LimitedNodeList const&); // Don't implement, needed to avoid copies of singleton
qint64 writeDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr, qint64 writeDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr);
const QUuid& connectionSecret);
PacketSequenceNumber getNextSequenceNumberForPacket(const QUuid& nodeUUID, PacketType packetType);
void changeSocketBufferSizes(int numBytes); void changeSocketBufferSizes(int numBytes);
@ -247,6 +258,8 @@ protected:
QElapsedTimer _packetStatTimer; QElapsedTimer _packetStatTimer;
bool _thisNodeCanAdjustLocks; bool _thisNodeCanAdjustLocks;
bool _thisNodeCanRez; bool _thisNodeCanRez;
std::unordered_map<QUuid, PacketTypeSequenceMap, UUIDHasher> _packetSequenceNumbers;
template<typename IteratorLambda> template<typename IteratorLambda>
void eachNodeHashIterator(IteratorLambda functor) { void eachNodeHashIterator(IteratorLambda functor) {

View file

@ -129,6 +129,15 @@ void Node::activateSymmetricSocket() {
_activeSocket = &_symmetricSocket; _activeSocket = &_symmetricSocket;
} }
PacketSequenceNumber Node::getLastSequenceNumberForPacketType(PacketType packetType) const {
auto typeMatch = _lastSequenceNumbers.find(packetType);
if (typeMatch != _lastSequenceNumbers.end()) {
return typeMatch->second;
} else {
return DEFAULT_SEQUENCE_NUMBER;
}
}
QDataStream& operator<<(QDataStream& out, const Node& node) { QDataStream& operator<<(QDataStream& out, const Node& node) {
out << node._type; out << node._type;
out << node._uuid; out << node._uuid;

View file

@ -23,6 +23,7 @@
#include "HifiSockAddr.h" #include "HifiSockAddr.h"
#include "NetworkPeer.h" #include "NetworkPeer.h"
#include "NodeData.h" #include "NodeData.h"
#include "PacketHeaders.h"
#include "SimpleMovingAverage.h" #include "SimpleMovingAverage.h"
#include "MovingPercentile.h" #include "MovingPercentile.h"
@ -43,7 +44,7 @@ namespace NodeType {
class Node : public NetworkPeer { class Node : public NetworkPeer {
Q_OBJECT Q_OBJECT
public: public:
Node(const QUuid& uuid, NodeType_t type, Node(const QUuid& uuid, NodeType_t type,
const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, bool canAdjustLocks, bool canRez); const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, bool canAdjustLocks, bool canRez);
~Node(); ~Node();
@ -86,6 +87,10 @@ public:
void activatePublicSocket(); void activatePublicSocket();
void activateLocalSocket(); void activateLocalSocket();
void activateSymmetricSocket(); void activateSymmetricSocket();
void setLastSequenceNumberForPacketType(PacketSequenceNumber sequenceNumber, PacketType packetType)
{ _lastSequenceNumbers[packetType] = sequenceNumber; }
PacketSequenceNumber getLastSequenceNumberForPacketType(PacketType packetType) const;
friend QDataStream& operator<<(QDataStream& out, const Node& node); friend QDataStream& operator<<(QDataStream& out, const Node& node);
friend QDataStream& operator>>(QDataStream& in, Node& node); friend QDataStream& operator>>(QDataStream& in, Node& node);
@ -109,6 +114,8 @@ private:
MovingPercentile _clockSkewMovingPercentile; MovingPercentile _clockSkewMovingPercentile;
bool _canAdjustLocks; bool _canAdjustLocks;
bool _canRez; bool _canRez;
PacketTypeSequenceMap _lastSequenceNumbers;
}; };
QDebug operator<<(QDebug debug, const Node &message); QDebug operator<<(QDebug debug, const Node &message);

View file

@ -183,7 +183,7 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr
} }
case PacketTypePingReply: { case PacketTypePingReply: {
SharedNodePointer sendingNode = sendingNodeForPacket(packet); SharedNodePointer sendingNode = sendingNodeForPacket(packet);
if (sendingNode) { if (sendingNode) {
sendingNode->setLastHeardMicrostamp(usecTimestampNow()); sendingNode->setLastHeardMicrostamp(usecTimestampNow());
@ -348,7 +348,7 @@ void NodeList::sendDomainServerCheckIn() {
} }
} }
QByteArray domainServerPacket = byteArrayWithPopulatedHeader(domainPacketType, packetUUID); QByteArray domainServerPacket = byteArrayWithUUIDPopulatedHeader(domainPacketType, packetUUID);
QDataStream packetStream(&domainServerPacket, QIODevice::Append); QDataStream packetStream(&domainServerPacket, QIODevice::Append);
// pack our data to send to the domain-server // pack our data to send to the domain-server
@ -369,7 +369,7 @@ void NodeList::sendDomainServerCheckIn() {
} }
if (!isUsingDTLS) { if (!isUsingDTLS) {
writeDatagram(domainServerPacket, _domainHandler.getSockAddr(), QUuid()); writeUnverifiedDatagram(domainServerPacket, _domainHandler.getSockAddr());
} }
const int NUM_DOMAIN_SERVER_CHECKINS_PER_STUN_REQUEST = 5; const int NUM_DOMAIN_SERVER_CHECKINS_PER_STUN_REQUEST = 5;
@ -424,10 +424,9 @@ int NodeList::processDomainServerList(const QByteArray& packet) {
_domainHandler.setUUID(uuidFromPacketHeader(packet)); _domainHandler.setUUID(uuidFromPacketHeader(packet));
_domainHandler.setIsConnected(true); _domainHandler.setIsConnected(true);
} }
int readNodes = 0; int readNodes = 0;
QDataStream packetStream(packet); QDataStream packetStream(packet);
packetStream.skipRawData(numBytesForPacketHeader(packet)); packetStream.skipRawData(numBytesForPacketHeader(packet));
@ -497,7 +496,7 @@ void NodeList::pingPunchForInactiveNode(const SharedNodePointer& node) {
QByteArray publicPingPacket = constructPingPacket(PingType::Public); QByteArray publicPingPacket = constructPingPacket(PingType::Public);
writeDatagram(publicPingPacket, node, node->getPublicSocket()); writeDatagram(publicPingPacket, node, node->getPublicSocket());
if (!node->getSymmetricSocket().isNull()) { if (!node->getSymmetricSocket().isNull()) {
QByteArray symmetricPingPacket = constructPingPacket(PingType::Symmetric); QByteArray symmetricPingPacket = constructPingPacket(PingType::Symmetric);
writeDatagram(symmetricPingPacket, node, node->getSymmetricSocket()); writeDatagram(symmetricPingPacket, node, node->getSymmetricSocket());

View file

@ -9,14 +9,12 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include "PacketHeaders.h"
#include <math.h> #include <math.h>
#include <QtCore/QDebug> #include <QtCore/QDebug>
#include "NodeList.h"
#include "PacketHeaders.h"
int arithmeticCodingValueFromBuffer(const char* checkValue) { int arithmeticCodingValueFromBuffer(const char* checkValue) {
if (((uchar) *checkValue) < 255) { if (((uchar) *checkValue) < 255) {
return *checkValue; return *checkValue;
@ -45,8 +43,8 @@ int packArithmeticallyCodedValue(int value, char* destination) {
} }
} }
PacketVersion versionForPacketType(PacketType type) { PacketVersion versionForPacketType(PacketType packetType) {
switch (type) { switch (packetType) {
case PacketTypeMicrophoneAudioNoEcho: case PacketTypeMicrophoneAudioNoEcho:
case PacketTypeMicrophoneAudioWithEcho: case PacketTypeMicrophoneAudioWithEcho:
return 2; return 2;
@ -57,7 +55,7 @@ PacketVersion versionForPacketType(PacketType type) {
case PacketTypeInjectAudio: case PacketTypeInjectAudio:
return 1; return 1;
case PacketTypeAvatarData: case PacketTypeAvatarData:
return 5; return 6;
case PacketTypeAvatarIdentity: case PacketTypeAvatarIdentity:
return 1; return 1;
case PacketTypeEnvironmentData: case PacketTypeEnvironmentData:
@ -86,8 +84,8 @@ PacketVersion versionForPacketType(PacketType type) {
#define PACKET_TYPE_NAME_LOOKUP(x) case x: return QString(#x); #define PACKET_TYPE_NAME_LOOKUP(x) case x: return QString(#x);
QString nameForPacketType(PacketType type) { QString nameForPacketType(PacketType packetType) {
switch (type) { switch (packetType) {
PACKET_TYPE_NAME_LOOKUP(PacketTypeUnknown); PACKET_TYPE_NAME_LOOKUP(PacketTypeUnknown);
PACKET_TYPE_NAME_LOOKUP(PacketTypeStunResponse); PACKET_TYPE_NAME_LOOKUP(PacketTypeStunResponse);
PACKET_TYPE_NAME_LOOKUP(PacketTypeDomainList); PACKET_TYPE_NAME_LOOKUP(PacketTypeDomainList);
@ -132,71 +130,81 @@ QString nameForPacketType(PacketType type) {
PACKET_TYPE_NAME_LOOKUP(PacketTypeUnverifiedPing); PACKET_TYPE_NAME_LOOKUP(PacketTypeUnverifiedPing);
PACKET_TYPE_NAME_LOOKUP(PacketTypeUnverifiedPingReply); PACKET_TYPE_NAME_LOOKUP(PacketTypeUnverifiedPingReply);
default: default:
return QString("Type: ") + QString::number((int)type); return QString("Type: ") + QString::number((int)packetType);
} }
return QString("unexpected"); return QString("unexpected");
} }
QByteArray byteArrayWithPopulatedHeader(PacketType type, const QUuid& connectionUUID) { QByteArray byteArrayWithUUIDPopulatedHeader(PacketType packetType, const QUuid& connectionUUID) {
QByteArray freshByteArray(MAX_PACKET_HEADER_BYTES, 0); QByteArray freshByteArray(MAX_PACKET_HEADER_BYTES, 0);
freshByteArray.resize(populatePacketHeader(freshByteArray, type, connectionUUID)); freshByteArray.resize(populatePacketHeaderWithUUID(freshByteArray, packetType, connectionUUID));
return freshByteArray; return freshByteArray;
} }
int populatePacketHeader(QByteArray& packet, PacketType type, const QUuid& connectionUUID) { int populatePacketHeaderWithUUID(QByteArray& packet, PacketType packetType, const QUuid& connectionUUID) {
if (packet.size() < numBytesForPacketHeaderGivenPacketType(type)) { if (packet.size() < numBytesForPacketHeaderGivenPacketType(packetType)) {
packet.resize(numBytesForPacketHeaderGivenPacketType(type)); packet.resize(numBytesForPacketHeaderGivenPacketType(packetType));
} }
return populatePacketHeader(packet.data(), type, connectionUUID); return populatePacketHeaderWithUUID(packet.data(), packetType, connectionUUID);
} }
int populatePacketHeader(char* packet, PacketType type, const QUuid& connectionUUID) { int populatePacketHeaderWithUUID(char* packet, PacketType packetType, const QUuid& connectionUUID) {
int numTypeBytes = packArithmeticallyCodedValue(type, packet); int numTypeBytes = packArithmeticallyCodedValue(packetType, packet);
packet[numTypeBytes] = versionForPacketType(type); packet[numTypeBytes] = versionForPacketType(packetType);
char* position = packet + numTypeBytes + sizeof(PacketVersion); char* position = packet + numTypeBytes + sizeof(PacketVersion);
QUuid packUUID = connectionUUID.isNull() ? DependencyManager::get<LimitedNodeList>()->getSessionUUID() : connectionUUID; QByteArray rfcUUID = connectionUUID.toRfc4122();
QByteArray rfcUUID = packUUID.toRfc4122();
memcpy(position, rfcUUID.constData(), NUM_BYTES_RFC4122_UUID); memcpy(position, rfcUUID.constData(), NUM_BYTES_RFC4122_UUID);
position += NUM_BYTES_RFC4122_UUID; position += NUM_BYTES_RFC4122_UUID;
if (!NON_VERIFIED_PACKETS.contains(type)) { if (!NON_VERIFIED_PACKETS.contains(packetType)) {
// pack 16 bytes of zeros where the md5 hash will be placed once data is packed // pack 16 bytes of zeros where the md5 hash will be placed once data is packed
memset(position, 0, NUM_BYTES_MD5_HASH); memset(position, 0, NUM_BYTES_MD5_HASH);
position += NUM_BYTES_MD5_HASH; position += NUM_BYTES_MD5_HASH;
} }
if (SEQUENCE_NUMBERED_PACKETS.contains(packetType)) {
// Pack zeros for the number of bytes that the sequence number requires.
// The LimitedNodeList will handle packing in the sequence number when sending out the packet.
memset(position, 0, sizeof(PacketSequenceNumber));
position += sizeof(PacketSequenceNumber);
}
// return the number of bytes written for pointer pushing // return the number of bytes written for pointer pushing
return position - packet; return position - packet;
} }
int numBytesForPacketHeader(const QByteArray& packet) { int numBytesForPacketHeader(const QByteArray& packet) {
// returns the number of bytes used for the type, version, and UUID PacketType packetType = packetTypeForPacket(packet);
return numBytesArithmeticCodingFromBuffer(packet.data()) return numBytesForPacketHeaderGivenPacketType(packetType);
+ numHashBytesInPacketHeaderGivenPacketType(packetTypeForPacket(packet))
+ 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 PacketType packetType = packetTypeForPacket(packet);
return numBytesArithmeticCodingFromBuffer(packet) return numBytesForPacketHeaderGivenPacketType(packetType);
+ numHashBytesInPacketHeaderGivenPacketType(packetTypeForPacket(packet)) }
int numBytesForArithmeticCodedPacketType(PacketType packetType) {
return (int) ceilf((float) packetType / 255);
}
int numBytesForPacketHeaderGivenPacketType(PacketType packetType) {
return numBytesForArithmeticCodedPacketType(packetType)
+ numHashBytesForType(packetType)
+ numSequenceNumberBytesForType(packetType)
+ NUM_STATIC_HEADER_BYTES; + NUM_STATIC_HEADER_BYTES;
} }
int numBytesForPacketHeaderGivenPacketType(PacketType type) { int numHashBytesForType(PacketType packetType) {
return (int) ceilf((float)type / 255) return (NON_VERIFIED_PACKETS.contains(packetType) ? 0 : NUM_BYTES_MD5_HASH);
+ numHashBytesInPacketHeaderGivenPacketType(type)
+ NUM_STATIC_HEADER_BYTES;
} }
int numHashBytesInPacketHeaderGivenPacketType(PacketType type) { int numSequenceNumberBytesForType(PacketType packetType) {
return (NON_VERIFIED_PACKETS.contains(type) ? 0 : NUM_BYTES_MD5_HASH); return (SEQUENCE_NUMBERED_PACKETS.contains(packetType) ? sizeof(PacketSequenceNumber) : 0);
} }
QUuid uuidFromPacketHeader(const QByteArray& packet) { QUuid uuidFromPacketHeader(const QByteArray& packet) {
@ -204,8 +212,16 @@ QUuid uuidFromPacketHeader(const QByteArray& packet) {
NUM_BYTES_RFC4122_UUID)); NUM_BYTES_RFC4122_UUID));
} }
int hashOffsetForPacketType(PacketType packetType) {
return numBytesForArithmeticCodedPacketType(packetType) + NUM_STATIC_HEADER_BYTES;
}
int sequenceNumberOffsetForPacketType(PacketType packetType) {
return numBytesForPacketHeaderGivenPacketType(packetType) - sizeof(PacketSequenceNumber);
}
QByteArray hashFromPacketHeader(const QByteArray& packet) { QByteArray hashFromPacketHeader(const QByteArray& packet) {
return packet.mid(numBytesForPacketHeader(packet) - NUM_BYTES_MD5_HASH, NUM_BYTES_MD5_HASH); return packet.mid(hashOffsetForPacketType(packetTypeForPacket(packet)), NUM_BYTES_MD5_HASH);
} }
QByteArray hashForPacketAndConnectionUUID(const QByteArray& packet, const QUuid& connectionUUID) { QByteArray hashForPacketAndConnectionUUID(const QByteArray& packet, const QUuid& connectionUUID) {
@ -213,11 +229,48 @@ QByteArray hashForPacketAndConnectionUUID(const QByteArray& packet, const QUuid&
QCryptographicHash::Md5); QCryptographicHash::Md5);
} }
void replaceHashInPacketGivenConnectionUUID(QByteArray& packet, const QUuid& connectionUUID) { PacketSequenceNumber sequenceNumberFromHeader(const QByteArray& packet, PacketType packetType) {
packet.replace(numBytesForPacketHeader(packet) - NUM_BYTES_MD5_HASH, NUM_BYTES_MD5_HASH, if (packetType == PacketTypeUnknown) {
packetType = packetTypeForPacket(packet);
}
PacketSequenceNumber result = DEFAULT_SEQUENCE_NUMBER;
if (SEQUENCE_NUMBERED_PACKETS.contains(packetType)) {
memcpy(&result, packet.data() + sequenceNumberOffsetForPacketType(packetType), sizeof(PacketSequenceNumber));
}
return result;
}
void replaceHashInPacket(QByteArray& packet, const QUuid& connectionUUID, PacketType packetType) {
if (packetType == PacketTypeUnknown) {
packetType = packetTypeForPacket(packet);
}
packet.replace(hashOffsetForPacketType(packetType), NUM_BYTES_MD5_HASH,
hashForPacketAndConnectionUUID(packet, connectionUUID)); hashForPacketAndConnectionUUID(packet, connectionUUID));
} }
void replaceSequenceNumberInPacket(QByteArray& packet, PacketSequenceNumber sequenceNumber, PacketType packetType) {
if (packetType == PacketTypeUnknown) {
packetType = packetTypeForPacket(packet);
}
packet.replace(sequenceNumberOffsetForPacketType(packetType),
sizeof(PacketSequenceNumber), reinterpret_cast<char*>(&sequenceNumber), sizeof(PacketSequenceNumber));
}
void replaceHashAndSequenceNumberInPacket(QByteArray& packet, const QUuid& connectionUUID, PacketSequenceNumber sequenceNumber,
PacketType packetType) {
if (packetType == PacketTypeUnknown) {
packetType = packetTypeForPacket(packet);
}
replaceHashInPacket(packet, connectionUUID, packetType);
replaceSequenceNumberInPacket(packet, sequenceNumber, packetType);
}
PacketType packetTypeForPacket(const QByteArray& packet) { PacketType packetTypeForPacket(const QByteArray& packet) {
return (PacketType) arithmeticCodingValueFromBuffer(packet.data()); return (PacketType) arithmeticCodingValueFromBuffer(packet.data());
} }

View file

@ -12,14 +12,19 @@
#ifndef hifi_PacketHeaders_h #ifndef hifi_PacketHeaders_h
#define hifi_PacketHeaders_h #define hifi_PacketHeaders_h
#pragma once
#include <cstdint>
#include <map>
#include <QtCore/QCryptographicHash> #include <QtCore/QCryptographicHash>
#include <QtCore/QSet> #include <QtCore/QSet>
#include <QtCore/QUuid> #include <QtCore/QUuid>
#include "UUID.h" #include "UUID.h"
// NOTE: if adding a new packet type, you can replace one marked usable or add at the end // NOTE: if adding a new packet packetType, you can replace one marked usable or add at the end
// NOTE: if you want the name of the packet type to be available for debugging or logging, update nameForPacketType() as well // NOTE: if you want the name of the packet packetType to be available for debugging or logging, update nameForPacketType() as well
enum PacketType { enum PacketType {
PacketTypeUnknown, // 0 PacketTypeUnknown, // 0
PacketTypeStunResponse, PacketTypeStunResponse,
@ -79,6 +84,11 @@ enum PacketType {
typedef char PacketVersion; typedef char PacketVersion;
typedef uint16_t PacketSequenceNumber;
const PacketSequenceNumber DEFAULT_SEQUENCE_NUMBER = 0;
typedef std::map<PacketType, PacketSequenceNumber> PacketTypeSequenceMap;
const QSet<PacketType> NON_VERIFIED_PACKETS = QSet<PacketType>() const QSet<PacketType> NON_VERIFIED_PACKETS = QSet<PacketType>()
<< PacketTypeDomainServerRequireDTLS << PacketTypeDomainConnectRequest << PacketTypeDomainServerRequireDTLS << PacketTypeDomainConnectRequest
<< PacketTypeDomainList << PacketTypeDomainListRequest << PacketTypeDomainConnectionDenied << PacketTypeDomainList << PacketTypeDomainListRequest << PacketTypeDomainConnectionDenied
@ -88,33 +98,53 @@ const QSet<PacketType> NON_VERIFIED_PACKETS = QSet<PacketType>()
<< PacketTypeIceServerHeartbeat << PacketTypeIceServerHeartbeatResponse << PacketTypeIceServerHeartbeat << PacketTypeIceServerHeartbeatResponse
<< PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply << PacketTypeStopNode; << PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply << PacketTypeStopNode;
const QSet<PacketType> SEQUENCE_NUMBERED_PACKETS = QSet<PacketType>()
<< PacketTypeAvatarData;
const int NUM_BYTES_MD5_HASH = 16; const int NUM_BYTES_MD5_HASH = 16;
const int NUM_STATIC_HEADER_BYTES = sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID; const int NUM_STATIC_HEADER_BYTES = sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID;
const int MAX_PACKET_HEADER_BYTES = sizeof(PacketType) + NUM_BYTES_MD5_HASH + NUM_STATIC_HEADER_BYTES; const int MAX_PACKET_HEADER_BYTES = sizeof(PacketType) + NUM_BYTES_MD5_HASH + NUM_STATIC_HEADER_BYTES;
PacketVersion versionForPacketType(PacketType type); PacketType packetTypeForPacket(const QByteArray& packet);
QString nameForPacketType(PacketType type); PacketType packetTypeForPacket(const char* packet);
PacketVersion versionForPacketType(PacketType packetType);
QString nameForPacketType(PacketType packetType);
const QUuid nullUUID = QUuid(); const QUuid nullUUID = QUuid();
QByteArray byteArrayWithPopulatedHeader(PacketType type, const QUuid& connectionUUID = nullUUID); QByteArray byteArrayWithUUIDPopulatedHeader(PacketType packetType, const QUuid& connectionUUID);
int populatePacketHeader(QByteArray& packet, PacketType type, const QUuid& connectionUUID = nullUUID); int populatePacketHeaderWithUUID(QByteArray& packet, PacketType packetType, const QUuid& connectionUUID);
int populatePacketHeader(char* packet, PacketType type, const QUuid& connectionUUID = nullUUID); int populatePacketHeaderWithUUID(char* packet, PacketType packetType, const QUuid& connectionUUID);
int numHashBytesInPacketHeaderGivenPacketType(PacketType type); int numHashBytesForType(PacketType packetType);
int numSequenceNumberBytesForType(PacketType packetType);
int numBytesForPacketHeader(const QByteArray& packet); int numBytesForPacketHeader(const QByteArray& packet);
int numBytesForPacketHeader(const char* packet); int numBytesForPacketHeader(const char* packet);
int numBytesForPacketHeaderGivenPacketType(PacketType type); int numBytesForArithmeticCodedPacketType(PacketType packetType);
int numBytesForPacketHeaderGivenPacketType(PacketType packetType);
QUuid uuidFromPacketHeader(const QByteArray& packet); QUuid uuidFromPacketHeader(const QByteArray& packet);
int hashOffsetForPacketType(PacketType packetType);
int sequenceNumberOffsetForPacketType(PacketType packetType);
QByteArray hashFromPacketHeader(const QByteArray& packet); QByteArray hashFromPacketHeader(const QByteArray& packet);
QByteArray hashForPacketAndConnectionUUID(const QByteArray& packet, const QUuid& connectionUUID); QByteArray hashForPacketAndConnectionUUID(const QByteArray& packet, const QUuid& connectionUUID);
void replaceHashInPacketGivenConnectionUUID(QByteArray& packet, const QUuid& connectionUUID);
PacketType packetTypeForPacket(const QByteArray& packet); // NOTE: The following four methods accept a PacketType which defaults to PacketTypeUnknown.
PacketType packetTypeForPacket(const char* packet); // If the caller has already looked at the packet type and can provide it then the methods below won't have to look it up.
PacketSequenceNumber sequenceNumberFromHeader(const QByteArray& packet, PacketType packetType = PacketTypeUnknown);
void replaceHashInPacket(QByteArray& packet, const QUuid& connectionUUID, PacketType packetType = PacketTypeUnknown);
void replaceSequenceNumberInPacket(QByteArray& packet, PacketSequenceNumber sequenceNumber,
PacketType packetType = PacketTypeUnknown);
void replaceHashAndSequenceNumberInPacket(QByteArray& packet, const QUuid& connectionUUID, PacketSequenceNumber sequenceNumber,
PacketType packetType = PacketTypeUnknown);
int arithmeticCodingValueFromBuffer(const char* checkValue); int arithmeticCodingValueFromBuffer(const char* checkValue);
int numBytesArithmeticCodingFromBuffer(const char* checkValue); int numBytesArithmeticCodingFromBuffer(const char* checkValue);

View file

@ -35,10 +35,13 @@ void JurisdictionListener::nodeKilled(SharedNodePointer node) {
bool JurisdictionListener::queueJurisdictionRequest() { bool JurisdictionListener::queueJurisdictionRequest() {
static unsigned char buffer[MAX_PACKET_SIZE]; static unsigned char buffer[MAX_PACKET_SIZE];
unsigned char* bufferOut = &buffer[0]; unsigned char* bufferOut = &buffer[0];
int sizeOut = populatePacketHeader(reinterpret_cast<char*>(bufferOut), PacketTypeJurisdictionRequest);
auto nodeList = DependencyManager::get<NodeList>();
int sizeOut = nodeList->populatePacketHeader(reinterpret_cast<char*>(bufferOut), PacketTypeJurisdictionRequest);
int nodeCount = 0; int nodeCount = 0;
DependencyManager::get<NodeList>()->eachNode([&](const SharedNodePointer& node) { nodeList->eachNode([&](const SharedNodePointer& node) {
if (node->getType() == getNodeType() && node->getActiveSocket()) { if (node->getType() == getNodeType() && node->getActiveSocket()) {
_packetSender.queuePacketForSending(node, QByteArray(reinterpret_cast<char*>(bufferOut), sizeOut)); _packetSender.queuePacketForSending(node, QByteArray(reinterpret_cast<char*>(bufferOut), sizeOut));
nodeCount++; nodeCount++;

View file

@ -14,6 +14,8 @@
#include <QStringList> #include <QStringList>
#include <QDebug> #include <QDebug>
#include <DependencyManager.h>
#include <NodeList.h>
#include <PacketHeaders.h> #include <PacketHeaders.h>
#include <OctalCode.h> #include <OctalCode.h>
@ -268,8 +270,9 @@ bool JurisdictionMap::writeToFile(const char* filename) {
int JurisdictionMap::packEmptyJurisdictionIntoMessage(NodeType_t type, unsigned char* destinationBuffer, int availableBytes) { int JurisdictionMap::packEmptyJurisdictionIntoMessage(NodeType_t type, unsigned char* destinationBuffer, int availableBytes) {
unsigned char* bufferStart = destinationBuffer; unsigned char* bufferStart = destinationBuffer;
int headerLength = populatePacketHeader(reinterpret_cast<char*>(destinationBuffer), PacketTypeJurisdiction); int headerLength = DependencyManager::get<NodeList>()->populatePacketHeader(reinterpret_cast<char*>(destinationBuffer),
PacketTypeJurisdiction);
destinationBuffer += headerLength; destinationBuffer += headerLength;
// Pack the Node Type in first byte // Pack the Node Type in first byte
@ -287,7 +290,8 @@ int JurisdictionMap::packEmptyJurisdictionIntoMessage(NodeType_t type, unsigned
int JurisdictionMap::packIntoMessage(unsigned char* destinationBuffer, int availableBytes) { int JurisdictionMap::packIntoMessage(unsigned char* destinationBuffer, int availableBytes) {
unsigned char* bufferStart = destinationBuffer; unsigned char* bufferStart = destinationBuffer;
int headerLength = populatePacketHeader(reinterpret_cast<char*>(destinationBuffer), PacketTypeJurisdiction); int headerLength = DependencyManager::get<NodeList>()->populatePacketHeader(reinterpret_cast<char*>(destinationBuffer),
PacketTypeJurisdiction);
destinationBuffer += headerLength; destinationBuffer += headerLength;
// Pack the Node Type in first byte // Pack the Node Type in first byte

View file

@ -328,7 +328,8 @@ void OctreeEditPacketSender::releaseQueuedPacket(EditPacketBuffer& packetBuffer)
} }
void OctreeEditPacketSender::initializePacket(EditPacketBuffer& packetBuffer, PacketType type, int nodeClockSkew) { void OctreeEditPacketSender::initializePacket(EditPacketBuffer& packetBuffer, PacketType type, int nodeClockSkew) {
packetBuffer._currentSize = populatePacketHeader(reinterpret_cast<char*>(&packetBuffer._currentBuffer[0]), type); packetBuffer._currentSize =
DependencyManager::get<NodeList>()->populatePacketHeader(reinterpret_cast<char*>(&packetBuffer._currentBuffer[0]), type);
// skip over sequence number for now; will be packed when packet is ready to be sent out // skip over sequence number for now; will be packed when packet is ready to be sent out
packetBuffer._currentSize += sizeof(quint16); packetBuffer._currentSize += sizeof(quint16);

View file

@ -221,7 +221,7 @@ void OctreeHeadlessViewer::queryOctree() {
unsigned char* endOfQueryPacket = queryPacket; unsigned char* endOfQueryPacket = queryPacket;
// insert packet type/version and node UUID // insert packet type/version and node UUID
endOfQueryPacket += populatePacketHeader(reinterpret_cast<char*>(endOfQueryPacket), packetType); endOfQueryPacket += nodeList->populatePacketHeader(reinterpret_cast<char*>(endOfQueryPacket), packetType);
// encode the query data... // encode the query data...
endOfQueryPacket += _octreeQuery.getBroadcastData(endOfQueryPacket); endOfQueryPacket += _octreeQuery.getBroadcastData(endOfQueryPacket);

View file

@ -385,7 +385,8 @@ void OctreeSceneStats::childBitsRemoved(bool includesExistsBits, bool includesCo
int OctreeSceneStats::packIntoMessage(unsigned char* destinationBuffer, int availableBytes) { int OctreeSceneStats::packIntoMessage(unsigned char* destinationBuffer, int availableBytes) {
unsigned char* bufferStart = destinationBuffer; unsigned char* bufferStart = destinationBuffer;
int headerLength = populatePacketHeader(reinterpret_cast<char*>(destinationBuffer), PacketTypeOctreeStats); int headerLength = DependencyManager::get<NodeList>()->populatePacketHeader(reinterpret_cast<char*>(destinationBuffer),
PacketTypeOctreeStats);
destinationBuffer += headerLength; destinationBuffer += headerLength;
memcpy(destinationBuffer, &_start, sizeof(_start)); memcpy(destinationBuffer, &_start, sizeof(_start));

View file

@ -493,7 +493,7 @@ void ScriptEngine::run() {
/ (1000 * 1000)) + 0.5); / (1000 * 1000)) + 0.5);
const int SCRIPT_AUDIO_BUFFER_BYTES = SCRIPT_AUDIO_BUFFER_SAMPLES * sizeof(int16_t); const int SCRIPT_AUDIO_BUFFER_BYTES = SCRIPT_AUDIO_BUFFER_SAMPLES * sizeof(int16_t);
QByteArray avatarPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarData); QByteArray avatarPacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeAvatarData);
avatarPacket.append(_avatarData->toByteArray()); avatarPacket.append(_avatarData->toByteArray());
nodeList->broadcastToNodes(avatarPacket, NodeSet() << NodeType::AvatarMixer); nodeList->broadcastToNodes(avatarPacket, NodeSet() << NodeType::AvatarMixer);
@ -534,9 +534,9 @@ void ScriptEngine::run() {
} }
} }
QByteArray audioPacket = byteArrayWithPopulatedHeader(silentFrame QByteArray audioPacket = nodeList->byteArrayWithPopulatedHeader(silentFrame
? PacketTypeSilentAudioFrame ? PacketTypeSilentAudioFrame
: PacketTypeMicrophoneAudioNoEcho); : PacketTypeMicrophoneAudioNoEcho);
QDataStream packetStream(&audioPacket, QIODevice::Append); QDataStream packetStream(&audioPacket, QIODevice::Append);