From 1a7e3a859cafe5c344b912b221580f12981abd92 Mon Sep 17 00:00:00 2001 From: wangyix Date: Thu, 5 Jun 2014 18:00:58 -0700 Subject: [PATCH 01/18] started work on resending nacked packets --- assignment-client/src/models/ModelServer.cpp | 2 +- .../src/octree/OctreeQueryNode.cpp | 35 ++++++++++++++- .../src/octree/OctreeQueryNode.h | 16 ++++++- .../src/octree/OctreeSendThread.cpp | 36 ++++++++++++++- .../src/octree/OctreeSendThread.h | 3 ++ assignment-client/src/octree/OctreeServer.cpp | 28 ++++++++++-- .../src/octree/SentPacketHistory.cpp | 45 +++++++++++++++++++ .../src/octree/SentPacketHistory.h | 36 +++++++++++++++ .../src/particles/ParticleServer.cpp | 2 +- assignment-client/src/voxels/VoxelServer.cpp | 2 +- libraries/networking/src/PacketHeaders.h | 1 + 11 files changed, 196 insertions(+), 10 deletions(-) create mode 100644 assignment-client/src/octree/SentPacketHistory.cpp create mode 100644 assignment-client/src/octree/SentPacketHistory.h diff --git a/assignment-client/src/models/ModelServer.cpp b/assignment-client/src/models/ModelServer.cpp index ff2367ec6e..07359f001a 100644 --- a/assignment-client/src/models/ModelServer.cpp +++ b/assignment-client/src/models/ModelServer.cpp @@ -106,7 +106,7 @@ int ModelServer::sendSpecialPacket(OctreeQueryNode* queryNode, const SharedNodeP //qDebug() << "sending PacketType_MODEL_ERASE packetLength:" << packetLength; NodeList::getInstance()->writeDatagram((char*) outputBuffer, packetLength, SharedNodePointer(node)); - queryNode->incrementSequenceNumber(); + queryNode->packetSent(outputBuffer, packetLength); } nodeData->setLastDeletedModelsSentAt(deletePacketSentAt); diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index 6acd85bff6..e0ca6a4f1e 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -41,7 +41,8 @@ OctreeQueryNode::OctreeQueryNode() : _sequenceNumber(0), _lastRootTimestamp(0), _myPacketType(PacketTypeUnknown), - _isShuttingDown(false) + _isShuttingDown(false), + _sentPacketHistory(1000) { } @@ -362,3 +363,35 @@ void OctreeQueryNode::dumpOutOfView() { } } } + +void OctreeQueryNode::packetSent() { + packetSent(_octreePacket, getPacketLength()); +} + +void OctreeQueryNode::packetSent(unsigned char* packet, int packetLength) { + packetSent(QByteArray((char*)packet, packetLength)); +} + +void OctreeQueryNode::packetSent(const QByteArray& packet) { + _sentPacketHistory.packetSent(_sequenceNumber, packet); + _sequenceNumber++; +} + + +void OctreeQueryNode::addSequenceNumbersToResend(const QList& sequenceNumbers) { + _sequenceNumbersToResend.append(sequenceNumbers); +} + +bool OctreeQueryNode::hasNextPacketToResend() const { + return !_sequenceNumbersToResend.isEmpty(); +} + +const QByteArray* OctreeQueryNode::getNextPacketToResend() { + + if (!_sequenceNumbersToResend.isEmpty()) { + const QByteArray* nextPacket = _sentPacketHistory.getPacket(_sequenceNumbersToResend.first()); + _sequenceNumbersToResend.pop_front(); + return nextPacket; // could be null + } + return NULL; +} \ No newline at end of file diff --git a/assignment-client/src/octree/OctreeQueryNode.h b/assignment-client/src/octree/OctreeQueryNode.h index eb420039e6..4a2355f7cc 100644 --- a/assignment-client/src/octree/OctreeQueryNode.h +++ b/assignment-client/src/octree/OctreeQueryNode.h @@ -23,6 +23,9 @@ #include #include #include // for SharedAssignmentPointer +#include "SentPacketHistory.h" + +#include // i added dis class OctreeSendThread; @@ -100,10 +103,16 @@ public: void forceNodeShutdown(); bool isShuttingDown() const { return _isShuttingDown; } - void incrementSequenceNumber() { _sequenceNumber++; } + void packetSent(); + void packetSent(unsigned char* packet, int packetLength); + void packetSent(const QByteArray& packet); OCTREE_PACKET_SEQUENCE getSequenceNumber() const { return _sequenceNumber; } - + + void addSequenceNumbersToResend(const QList& sequenceNumbers); + bool hasNextPacketToResend() const; + const QByteArray* getNextPacketToResend(); + private slots: void sendThreadFinished(); @@ -146,6 +155,9 @@ private: PacketType _myPacketType; bool _isShuttingDown; + +SentPacketHistory _sentPacketHistory; +QQueue _sequenceNumbersToResend; }; #endif // hifi_OctreeQueryNode_h diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 9e4dbcd347..5767f2623b 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -274,13 +274,47 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes trueBytesSent += nodeData->getPacketLength(); truePacketsSent++; packetsSent++; - nodeData->incrementSequenceNumber(); + nodeData->packetSent(); nodeData->resetOctreePacket(); } return packetsSent; } + + + + +int OctreeSendThread::resendNackedPackets(OctreeQueryNode* nodeData) { + + int packetsSent = 0; + + const QByteArray* packet; + while (nodeData->hasNextPacketToResend()) { + packet = nodeData->getNextPacketToResend(); + if (packet) { + NodeList::getInstance()->writeDatagram(*packet, _node); + packetsSent++; + + // ?????? + _totalBytes += packet->size(); + _totalPackets++; + _totalWastedBytes += MAX_PACKET_SIZE - packet->size(); // ??? + } + } + +} + + + + + + + + + + + /// Version of voxel distributor that sends the deepest LOD level at once int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrustumChanged) { diff --git a/assignment-client/src/octree/OctreeSendThread.h b/assignment-client/src/octree/OctreeSendThread.h index d8eed27802..cc0cdac3ad 100644 --- a/assignment-client/src/octree/OctreeSendThread.h +++ b/assignment-client/src/octree/OctreeSendThread.h @@ -55,6 +55,9 @@ private: int _nodeMissingCount; bool _isShuttingDown; + +int resendNackedPackets(OctreeQueryNode* nodeData); + }; #endif // hifi_OctreeSendThread_h diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 5769c15ef1..f60f0fc2d5 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -832,14 +832,14 @@ void OctreeServer::readPendingDatagrams() { PacketType packetType = packetTypeForPacket(receivedPacket); SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket); if (packetType == getMyQueryMessageType()) { - + // If we got a query packet, then we're talking to an agent, and we // need to make sure we have it in our nodeList. if (matchingNode) { nodeList->updateNodeWithDataFromPacket(matchingNode, receivedPacket); - OctreeQueryNode* nodeData = (OctreeQueryNode*) matchingNode->getLinkedData(); + OctreeQueryNode* nodeData = (OctreeQueryNode*)matchingNode->getLinkedData(); if (nodeData && !nodeData->isOctreeSendThreadInitalized()) { - + // NOTE: this is an important aspect of the proper ref counting. The send threads/node data need to // know that the OctreeServer/Assignment will not get deleted on it while it's still active. The // solution is to get the shared pointer for the current assignment. We need to make sure this is the @@ -848,6 +848,28 @@ void OctreeServer::readPendingDatagrams() { nodeData->initializeOctreeSendThread(sharedAssignment, matchingNode); } } + + } else if (packetType == PacketTypeOctreeDataNack) { + +// parse packet for sequence numbers that need to be resent +int numBytesPacketHeader = numBytesForPacketHeader(receivedPacket); +const unsigned char* dataAt = reinterpret_cast(receivedPacket.data()) + numBytesPacketHeader; + +uint16_t numSequenceNumbers = (*(uint16_t*)dataAt); +dataAt += sizeof(uint16_t); + +// read sequence numbers +QList sequenceNumbers; +for (int i = 0; i < numSequenceNumbers; i++) { + sequenceNumbers.append(*(OCTREE_PACKET_SEQUENCE*)dataAt); + dataAt += sizeof(OCTREE_PACKET_SEQUENCE); +} + +OctreeQueryNode* nodeData = (OctreeQueryNode*)matchingNode->getLinkedData(); // move this or something +nodeData->addSequenceNumbersToResend(sequenceNumbers); + + + } else if (packetType == PacketTypeJurisdictionRequest) { _jurisdictionSender->queueReceivedPacket(matchingNode, receivedPacket); } else if (_octreeInboundPacketProcessor && getOctree()->handlesEditPacketType(packetType)) { diff --git a/assignment-client/src/octree/SentPacketHistory.cpp b/assignment-client/src/octree/SentPacketHistory.cpp new file mode 100644 index 0000000000..0de163a23d --- /dev/null +++ b/assignment-client/src/octree/SentPacketHistory.cpp @@ -0,0 +1,45 @@ +// +// SentPacketHistory.cpp +// assignement-client/src/octree +// +// Created by Yixin Wang on 6/5/2014 +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "SentPacketHistory.h" + +SentPacketHistory::SentPacketHistory(int size) + : _sentPackets(size), + _newestPacketAt(0), + _numExistingPackets(0), + _newestSequenceNumber(0) +{ +} + +void SentPacketHistory::packetSent(OCTREE_PACKET_SEQUENCE sequenceNumber, const QByteArray& packet) { + _newestSequenceNumber = sequenceNumber; + + // increment _newestPacketAt cyclically, insert new packet there + _newestPacketAt = (_newestPacketAt == _sentPackets.size() - 1) ? 0 : _newestPacketAt + 1; + _sentPackets[_newestPacketAt] = packet; + + if (_numExistingPackets < _sentPackets.size()) { + _numExistingPackets++; + } +} + + +const QByteArray* SentPacketHistory::getPacket(OCTREE_PACKET_SEQUENCE sequenceNumber) const { + + OCTREE_PACKET_SEQUENCE seqDiff = _newestSequenceNumber - sequenceNumber; + if (!(seqDiff >= 0 && seqDiff < _numExistingPackets)) { + return NULL; + } + + int packetAt = _newestPacketAt - seqDiff; + if (packetAt < 0) { packetAt += _sentPackets.size(); } + + return &_sentPackets.at(packetAt); +} \ No newline at end of file diff --git a/assignment-client/src/octree/SentPacketHistory.h b/assignment-client/src/octree/SentPacketHistory.h new file mode 100644 index 0000000000..cbc50bc73c --- /dev/null +++ b/assignment-client/src/octree/SentPacketHistory.h @@ -0,0 +1,36 @@ +// +// SentPacketHistory.h +// assignement-client/src/octree +// +// Created by Yixin Wang on 6/5/2014 +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_SentPacketHistory_h +#define hifi_SentPacketHistory_h + +#include +#include + +#include "OctreePacketData.h" + +class SentPacketHistory { + +public: + SentPacketHistory(int size); + + void packetSent(OCTREE_PACKET_SEQUENCE sequenceNumber, const QByteArray& packet); + const QByteArray* getPacket(OCTREE_PACKET_SEQUENCE sequenceNumber) const; + +private: + + QVector _sentPackets; // circular buffer + int _newestPacketAt; + int _numExistingPackets; + + OCTREE_PACKET_SEQUENCE _newestSequenceNumber; +}; + +#endif diff --git a/assignment-client/src/particles/ParticleServer.cpp b/assignment-client/src/particles/ParticleServer.cpp index 1dd65f11f3..e7a0f75dfd 100644 --- a/assignment-client/src/particles/ParticleServer.cpp +++ b/assignment-client/src/particles/ParticleServer.cpp @@ -106,7 +106,7 @@ int ParticleServer::sendSpecialPacket(OctreeQueryNode* queryNode, const SharedNo //qDebug() << "sending PacketType_PARTICLE_ERASE packetLength:" << packetLength; NodeList::getInstance()->writeDatagram((char*) outputBuffer, packetLength, SharedNodePointer(node)); - queryNode->incrementSequenceNumber(); + queryNode->packetSent(outputBuffer, packetLength); } nodeData->setLastDeletedParticlesSentAt(deletePacketSentAt); diff --git a/assignment-client/src/voxels/VoxelServer.cpp b/assignment-client/src/voxels/VoxelServer.cpp index 8f4a8bab36..34b01f529a 100644 --- a/assignment-client/src/voxels/VoxelServer.cpp +++ b/assignment-client/src/voxels/VoxelServer.cpp @@ -75,7 +75,7 @@ int VoxelServer::sendSpecialPacket(OctreeQueryNode* queryNode, const SharedNodeP } NodeList::getInstance()->writeDatagram((char*) _tempOutputBuffer, envPacketLength, SharedNodePointer(node)); - queryNode->incrementSequenceNumber(); + queryNode->packetSent(_tempOutputBuffer, envPacketLength); return envPacketLength; } diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index 9c764f9f02..a73ffe8564 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -66,6 +66,7 @@ enum PacketType { PacketTypeModelAddOrEdit, PacketTypeModelErase, PacketTypeModelAddResponse, + PacketTypeOctreeDataNack }; typedef char PacketVersion; From 5461a06e992b2b7dd5bb2e1aff16a347a87963b6 Mon Sep 17 00:00:00 2001 From: wangyix Date: Fri, 6 Jun 2014 09:33:14 -0700 Subject: [PATCH 02/18] completed code to resend nacked packets on AC --- .../src/octree/OctreeQueryNode.cpp | 16 ++++++++-------- .../src/octree/OctreeQueryNode.h | 8 ++++---- .../src/octree/OctreeSendThread.cpp | 19 ++++++++++--------- assignment-client/src/octree/OctreeServer.cpp | 5 ++++- 4 files changed, 26 insertions(+), 22 deletions(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index e0ca6a4f1e..208be5951b 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -364,7 +364,7 @@ void OctreeQueryNode::dumpOutOfView() { } } -void OctreeQueryNode::packetSent() { +void OctreeQueryNode::octreePacketSent() { packetSent(_octreePacket, getPacketLength()); } @@ -379,18 +379,18 @@ void OctreeQueryNode::packetSent(const QByteArray& packet) { void OctreeQueryNode::addSequenceNumbersToResend(const QList& sequenceNumbers) { - _sequenceNumbersToResend.append(sequenceNumbers); + _nackedSequenceNumbers.append(sequenceNumbers); } -bool OctreeQueryNode::hasNextPacketToResend() const { - return !_sequenceNumbersToResend.isEmpty(); +bool OctreeQueryNode::hasNextNackedPacket() const { + return !_nackedSequenceNumbers.isEmpty(); } -const QByteArray* OctreeQueryNode::getNextPacketToResend() { +const QByteArray* OctreeQueryNode::getNextNackedPacket() { - if (!_sequenceNumbersToResend.isEmpty()) { - const QByteArray* nextPacket = _sentPacketHistory.getPacket(_sequenceNumbersToResend.first()); - _sequenceNumbersToResend.pop_front(); + if (!_nackedSequenceNumbers.isEmpty()) { + const QByteArray* nextPacket = _sentPacketHistory.getPacket(_nackedSequenceNumbers.first()); + _nackedSequenceNumbers.pop_front(); return nextPacket; // could be null } return NULL; diff --git a/assignment-client/src/octree/OctreeQueryNode.h b/assignment-client/src/octree/OctreeQueryNode.h index 4a2355f7cc..e1707cc899 100644 --- a/assignment-client/src/octree/OctreeQueryNode.h +++ b/assignment-client/src/octree/OctreeQueryNode.h @@ -103,15 +103,15 @@ public: void forceNodeShutdown(); bool isShuttingDown() const { return _isShuttingDown; } - void packetSent(); + void octreePacketSent(); void packetSent(unsigned char* packet, int packetLength); void packetSent(const QByteArray& packet); OCTREE_PACKET_SEQUENCE getSequenceNumber() const { return _sequenceNumber; } void addSequenceNumbersToResend(const QList& sequenceNumbers); - bool hasNextPacketToResend() const; - const QByteArray* getNextPacketToResend(); + bool hasNextNackedPacket() const; + const QByteArray* getNextNackedPacket(); private slots: void sendThreadFinished(); @@ -157,7 +157,7 @@ private: bool _isShuttingDown; SentPacketHistory _sentPacketHistory; -QQueue _sequenceNumbersToResend; +QQueue _nackedSequenceNumbers; }; #endif // hifi_OctreeQueryNode_h diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 5767f2623b..befea80380 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -85,6 +85,7 @@ bool OctreeSendThread::process() { if (nodeData && !nodeData->isShuttingDown()) { bool viewFrustumChanged = nodeData->updateCurrentViewFrustum(); packetDistributor(nodeData, viewFrustumChanged); +resendNackedPackets(nodeData); } } } @@ -274,7 +275,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes trueBytesSent += nodeData->getPacketLength(); truePacketsSent++; packetsSent++; - nodeData->packetSent(); + nodeData->octreePacketSent(); nodeData->resetOctreePacket(); } @@ -287,11 +288,14 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes int OctreeSendThread::resendNackedPackets(OctreeQueryNode* nodeData) { + const int maxPacketsSent = 10; + int packetsSent = 0; const QByteArray* packet; - while (nodeData->hasNextPacketToResend()) { - packet = nodeData->getNextPacketToResend(); + while (nodeData->hasNextNackedPacket() && packetsSent < maxPacketsSent) { + packet = nodeData->getNextNackedPacket(); + // packet will be NULL if it's not in nodeData's packet history if (packet) { NodeList::getInstance()->writeDatagram(*packet, _node); packetsSent++; @@ -302,7 +306,9 @@ int OctreeSendThread::resendNackedPackets(OctreeQueryNode* nodeData) { _totalWastedBytes += MAX_PACKET_SIZE - packet->size(); // ??? } } - + +printf("\t\t re-sent %d packets!\n", packetsSent); + return packetsSent; } @@ -310,11 +316,6 @@ int OctreeSendThread::resendNackedPackets(OctreeQueryNode* nodeData) { - - - - - /// Version of voxel distributor that sends the deepest LOD level at once int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrustumChanged) { diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index f60f0fc2d5..46eb7aac16 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -861,8 +861,11 @@ dataAt += sizeof(uint16_t); // read sequence numbers QList sequenceNumbers; for (int i = 0; i < numSequenceNumbers; i++) { - sequenceNumbers.append(*(OCTREE_PACKET_SEQUENCE*)dataAt); + OCTREE_PACKET_SEQUENCE sequenceNumber = (*(OCTREE_PACKET_SEQUENCE*)dataAt); + sequenceNumbers.append(sequenceNumber); dataAt += sizeof(OCTREE_PACKET_SEQUENCE); + +printf("\t\t\t nacked packet: seq = %d\n", sequenceNumber); } OctreeQueryNode* nodeData = (OctreeQueryNode*)matchingNode->getLinkedData(); // move this or something From 8cd5ec3b54e4e5b0f1cdebf2bf20833e8ebcac2b Mon Sep 17 00:00:00 2001 From: wangyix Date: Fri, 6 Jun 2014 11:50:34 -0700 Subject: [PATCH 03/18] started work on sending nack packets from client --- .../src/octree/OctreeSendThread.cpp | 4 +- interface/src/Application.cpp | 59 ++++++++++++++++++- interface/src/Application.h | 6 ++ libraries/octree/src/OctreeSceneStats.cpp | 15 +++++ libraries/octree/src/OctreeSceneStats.h | 4 ++ 5 files changed, 85 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index befea80380..032b45fcdf 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -288,12 +288,12 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes int OctreeSendThread::resendNackedPackets(OctreeQueryNode* nodeData) { - const int maxPacketsSent = 10; + const int MAX_PACKETS_RESEND = 10; int packetsSent = 0; const QByteArray* packet; - while (nodeData->hasNextNackedPacket() && packetsSent < maxPacketsSent) { + while (nodeData->hasNextNackedPacket() && packetsSent < MAX_PACKETS_RESEND) { packet = nodeData->getNextNackedPacket(); // packet will be NULL if it's not in nodeData's packet history if (packet) { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index de3c354b27..358bb1bde3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -167,7 +167,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _applicationOverlay(), _runningScriptsWidget(new RunningScriptsWidget(_window)), _runningScriptsWidgetWasVisible(false), - _trayIcon(new QSystemTrayIcon(_window)) + _trayIcon(new QSystemTrayIcon(_window)), + _lastNackTime(usecTimestampNow()) { // read the ApplicationInfo.ini file for Name/Version/Domain information QSettings applicationInfo(Application::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); @@ -2091,7 +2092,63 @@ void Application::updateMyAvatar(float deltaTime) { _lastQueriedViewFrustum = _viewFrustum; } } + +// sent a nack packet containing missing sequence numbers of received packets +{ + quint64 now = usecTimestampNow(); + quint64 sinceLastNack = now - _lastNackTime; + const quint64 TOO_LONG_SINCE_LAST_NACK = 100 * MSECS_PER_SECOND; + if (sinceLastNack > TOO_LONG_SINCE_LAST_NACK) { + _lastNackTime = now; + + //_octreeServerSceneStats- + } } +} + + +void Application::sendNack() { + /* + // now that we know the node ID, let's add these stats to the stats for that node... + _octreeSceneStatsLock.lockForWrite(); + if (_octreeServerSceneStats.find(nodeUUID) != _octreeServerSceneStats.end()) { + OctreeSceneStats& stats = _octreeServerSceneStats[nodeUUID]; + stats.trackIncomingOctreePacket(packet, wasStatsPacket, sendingNode->getClockSkewUsec()); + } + _octreeSceneStatsLock.unlock(); + */ + + char packet[MAX_PACKET_SIZE]; + NodeList* nodeList = NodeList::getInstance(); + + // iterates thru all nodes in NodeList + foreach(const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { + + char* dataAt = packet; + int bytesRemaining = MAX_PACKET_SIZE; + + int numBytesPacketHeader = populatePacketHeader(packet, PacketTypeOctreeDataNack, node->getUUID()); + dataAt += numBytesPacketHeader; + bytesRemaining -= numBytesPacketHeader; + + + + uint16_t numSequenceNumbers; + + + + + OctreeSceneStats& stats = _octreeServerSceneStats[node->getUUID()]; + int numSequenceNumbersAvailable = stats.getNumSequenceNumberToNack(); + + + // make sure we still have an active socket + nodeList->writeUnverifiedDatagram(reinterpret_cast(queryPacket), packetLength, node); + } +} + + + void Application::queryOctree(NodeType_t serverType, PacketType packetType, NodeToJurisdictionMap& jurisdictions) { diff --git a/interface/src/Application.h b/interface/src/Application.h index f3d9c0fd27..670ec35238 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -411,6 +411,10 @@ private: static void attachNewHeadToNode(Node *newNode); static void* networkReceive(void* args); // network receive thread + void sendNack(); + + + MainWindow* _window; GLCanvas* _glWidget; // our GLCanvas has a couple extra features @@ -580,6 +584,8 @@ private: bool _runningScriptsWidgetWasVisible; QSystemTrayIcon* _trayIcon; + +quint64 _lastNackTime; }; #endif // hifi_Application_h diff --git a/libraries/octree/src/OctreeSceneStats.cpp b/libraries/octree/src/OctreeSceneStats.cpp index 9580ae6d13..a25b72bedd 100644 --- a/libraries/octree/src/OctreeSceneStats.cpp +++ b/libraries/octree/src/OctreeSceneStats.cpp @@ -46,6 +46,7 @@ OctreeSceneStats::OctreeSceneStats() : _incomingReallyLate(0), _incomingPossibleDuplicate(0), _missingSequenceNumbers(), +_sequenceNumbersToNack(), _incomingFlightTimeAverage(samples), _jurisdictionRoot(NULL) { @@ -158,6 +159,7 @@ void OctreeSceneStats::copyFromOther(const OctreeSceneStats& other) { _incomingPossibleDuplicate = other._incomingPossibleDuplicate; _missingSequenceNumbers = other._missingSequenceNumbers; +_missingSequenceNumbersToNack = other._missingSequenceNumbersToNack; } @@ -926,6 +928,7 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, qDebug() << "found it in _missingSequenceNumbers"; } _missingSequenceNumbers.remove(sequence); +_sequenceNumbersToNack.remove(sequence); _incomingLikelyLost--; _incomingRecovered++; } else { @@ -955,6 +958,7 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, _incomingLikelyLost += missing; for(unsigned int missingSequence = expected; missingSequence < sequence; missingSequence++) { _missingSequenceNumbers << missingSequence; +_sequenceNumbersToNack << missingSequence; } } } @@ -982,9 +986,20 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, qDebug() << "pruning really old missing sequence:" << missingItem; } _missingSequenceNumbers.remove(missingItem); +_sequenceNumbersToNack.remove(missingItem); } } } } +bool OctreeSceneStats::getNumSequenceNumberToNack() const { + return _sequenceNumbersToNack.size(); +} + +uint16_t OctreeSceneStats::getNextSequenceNumberToNack() { + QSet::Iterator it = _sequenceNumbersToNack.begin(); + uint16_t sequenceNumber = *it; + _sequenceNumbersToNack.remove(sequenceNumber); + return sequenceNumber; +} \ No newline at end of file diff --git a/libraries/octree/src/OctreeSceneStats.h b/libraries/octree/src/OctreeSceneStats.h index ef22fd7c1c..e6664083b0 100644 --- a/libraries/octree/src/OctreeSceneStats.h +++ b/libraries/octree/src/OctreeSceneStats.h @@ -172,6 +172,9 @@ public: quint32 getIncomingPossibleDuplicate() const { return _incomingPossibleDuplicate; } float getIncomingFlightTimeAverage() { return _incomingFlightTimeAverage.getAverage(); } +bool getNumSequenceNumberToNack() const; +uint16_t getNextSequenceNumberToNack(); + private: void copyFromOther(const OctreeSceneStats& other); @@ -273,6 +276,7 @@ private: quint32 _incomingReallyLate; /// out of order and later than MAX_MISSING_SEQUENCE_OLD_AGE late quint32 _incomingPossibleDuplicate; /// out of order possibly a duplicate QSet _missingSequenceNumbers; +QSet _sequenceNumbersToNack; SimpleMovingAverage _incomingFlightTimeAverage; // features related items From 5c4748556206e940758b46d41625b25deb962f5c Mon Sep 17 00:00:00 2001 From: wangyix Date: Fri, 6 Jun 2014 14:27:51 -0700 Subject: [PATCH 04/18] client-side nack sending complete; ready to test --- interface/src/Application.cpp | 55 ++++++++++++----------- libraries/octree/src/OctreeSceneStats.cpp | 2 +- libraries/octree/src/OctreeSceneStats.h | 2 +- 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 358bb1bde3..7333960689 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2100,23 +2100,13 @@ void Application::updateMyAvatar(float deltaTime) { const quint64 TOO_LONG_SINCE_LAST_NACK = 100 * MSECS_PER_SECOND; if (sinceLastNack > TOO_LONG_SINCE_LAST_NACK) { _lastNackTime = now; - - //_octreeServerSceneStats- + sendNack(); } } } void Application::sendNack() { - /* - // now that we know the node ID, let's add these stats to the stats for that node... - _octreeSceneStatsLock.lockForWrite(); - if (_octreeServerSceneStats.find(nodeUUID) != _octreeServerSceneStats.end()) { - OctreeSceneStats& stats = _octreeServerSceneStats[nodeUUID]; - stats.trackIncomingOctreePacket(packet, wasStatsPacket, sendingNode->getClockSkewUsec()); - } - _octreeSceneStatsLock.unlock(); - */ char packet[MAX_PACKET_SIZE]; NodeList* nodeList = NodeList::getInstance(); @@ -2124,26 +2114,41 @@ void Application::sendNack() { // iterates thru all nodes in NodeList foreach(const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { - char* dataAt = packet; - int bytesRemaining = MAX_PACKET_SIZE; + if (node->getActiveSocket() && + ( node->getType() == NodeType::VoxelServer + || node->getType() == NodeType::ParticleServer + || node->getType() == NodeType::ModelServer) + ) { - int numBytesPacketHeader = populatePacketHeader(packet, PacketTypeOctreeDataNack, node->getUUID()); - dataAt += numBytesPacketHeader; - bytesRemaining -= numBytesPacketHeader; - - + OctreeSceneStats& stats = _octreeServerSceneStats[node->getUUID()]; - uint16_t numSequenceNumbers; + char* dataAt = packet; + int bytesRemaining = MAX_PACKET_SIZE; + + // pack header + int numBytesPacketHeader = populatePacketHeader(packet, PacketTypeOctreeDataNack, node->getUUID()); + dataAt += numBytesPacketHeader; + bytesRemaining -= numBytesPacketHeader; + + int numPacketsRoomFor = (bytesRemaining - sizeof(uint16_t)) / sizeof(OCTREE_PACKET_SEQUENCE); + // calculate and pack number of sequence numbers + uint16_t numSequenceNumbers = min(stats.getNumSequenceNumbersToNack(), numPacketsRoomFor); + uint16_t* numSequenceNumbersAt = (uint16_t*)dataAt; + *numSequenceNumbersAt = numSequenceNumbers; + dataAt += sizeof(uint16_t); + // pack sequence numbers + for (int i = 0; i < numSequenceNumbers; i++) { + OCTREE_PACKET_SEQUENCE* sequenceNumberAt = (OCTREE_PACKET_SEQUENCE*)dataAt; + *sequenceNumberAt = stats.getNextSequenceNumberToNack(); + dataAt += sizeof(OCTREE_PACKET_SEQUENCE); + } - OctreeSceneStats& stats = _octreeServerSceneStats[node->getUUID()]; - int numSequenceNumbersAvailable = stats.getNumSequenceNumberToNack(); - - - // make sure we still have an active socket - nodeList->writeUnverifiedDatagram(reinterpret_cast(queryPacket), packetLength, node); + // make sure we still have an active socket???? + nodeList->writeUnverifiedDatagram(packet, dataAt - packet, node); + } } } diff --git a/libraries/octree/src/OctreeSceneStats.cpp b/libraries/octree/src/OctreeSceneStats.cpp index a25b72bedd..01332fbc46 100644 --- a/libraries/octree/src/OctreeSceneStats.cpp +++ b/libraries/octree/src/OctreeSceneStats.cpp @@ -993,7 +993,7 @@ _sequenceNumbersToNack.remove(missingItem); } -bool OctreeSceneStats::getNumSequenceNumberToNack() const { +int OctreeSceneStats::getNumSequenceNumbersToNack() const { return _sequenceNumbersToNack.size(); } diff --git a/libraries/octree/src/OctreeSceneStats.h b/libraries/octree/src/OctreeSceneStats.h index e6664083b0..ca9bf7c74b 100644 --- a/libraries/octree/src/OctreeSceneStats.h +++ b/libraries/octree/src/OctreeSceneStats.h @@ -172,7 +172,7 @@ public: quint32 getIncomingPossibleDuplicate() const { return _incomingPossibleDuplicate; } float getIncomingFlightTimeAverage() { return _incomingFlightTimeAverage.getAverage(); } -bool getNumSequenceNumberToNack() const; +int getNumSequenceNumbersToNack() const; uint16_t getNextSequenceNumberToNack(); private: From bd2148d4b7eef48d46c6171f801521a4eb1dead8 Mon Sep 17 00:00:00 2001 From: wangyix Date: Fri, 6 Jun 2014 14:33:53 -0700 Subject: [PATCH 05/18] added write lock/unlock ...for _octreeSceneStatsLock --- interface/src/Application.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7333960689..6d6c7d64ab 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2120,6 +2120,8 @@ void Application::sendNack() { || node->getType() == NodeType::ModelServer) ) { + _octreeSceneStatsLock.lockForWrite(); + OctreeSceneStats& stats = _octreeServerSceneStats[node->getUUID()]; char* dataAt = packet; @@ -2146,6 +2148,8 @@ void Application::sendNack() { dataAt += sizeof(OCTREE_PACKET_SEQUENCE); } + _octreeSceneStatsLock.unlock(); + // make sure we still have an active socket???? nodeList->writeUnverifiedDatagram(packet, dataAt - packet, node); } From 0b1bffa83ca55957d174aa7e7fc0aa3e7916c07d Mon Sep 17 00:00:00 2001 From: wangyix Date: Fri, 6 Jun 2014 15:03:54 -0700 Subject: [PATCH 06/18] added random packet drops; ready to test --- .../src/octree/OctreeSendThread.cpp | 7 +++---- interface/src/Application.cpp | 7 ++++++- libraries/networking/src/LimitedNodeList.cpp | 17 +++++++++++++++++ libraries/networking/src/LimitedNodeList.h | 3 +++ libraries/octree/src/OctreeSceneStats.cpp | 2 +- 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 032b45fcdf..e5c47f5d2d 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -181,7 +181,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes // actually send it OctreeServer::didCallWriteDatagram(this); - NodeList::getInstance()->writeDatagram((char*) statsMessage, statsMessageLength, _node); +NodeList::getInstance()->writeDatagram2(nodeData->getSequenceNumber(), (char*) statsMessage, statsMessageLength, _node); packetSent = true; } else { // not enough room in the packet, send two packets @@ -215,8 +215,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes packetsSent++; OctreeServer::didCallWriteDatagram(this); - NodeList::getInstance()->writeDatagram((char*) nodeData->getPacket(), nodeData->getPacketLength(), _node); - +NodeList::getInstance()->writeDatagram2(nodeData->getSequenceNumber(), (char*)nodeData->getPacket(), nodeData->getPacketLength(), _node); packetSent = true; thisWastedBytes = MAX_PACKET_SIZE - nodeData->getPacketLength(); @@ -245,7 +244,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes if (nodeData->isPacketWaiting() && !nodeData->isShuttingDown()) { // just send the voxel packet OctreeServer::didCallWriteDatagram(this); - NodeList::getInstance()->writeDatagram((char*) nodeData->getPacket(), nodeData->getPacketLength(), _node); +NodeList::getInstance()->writeDatagram2(nodeData->getSequenceNumber(), (char*)nodeData->getPacket(), nodeData->getPacketLength(), _node); packetSent = true; int thisWastedBytes = MAX_PACKET_SIZE - nodeData->getPacketLength(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6d6c7d64ab..75980af934 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2097,7 +2097,7 @@ void Application::updateMyAvatar(float deltaTime) { { quint64 now = usecTimestampNow(); quint64 sinceLastNack = now - _lastNackTime; - const quint64 TOO_LONG_SINCE_LAST_NACK = 100 * MSECS_PER_SECOND; + const quint64 TOO_LONG_SINCE_LAST_NACK = 250 * MSECS_PER_SECOND; if (sinceLastNack > TOO_LONG_SINCE_LAST_NACK) { _lastNackTime = now; sendNack(); @@ -2108,6 +2108,8 @@ void Application::updateMyAvatar(float deltaTime) { void Application::sendNack() { +printf("\n\t sendNack()...\n"); + char packet[MAX_PACKET_SIZE]; NodeList* nodeList = NodeList::getInstance(); @@ -2142,11 +2144,14 @@ void Application::sendNack() { dataAt += sizeof(uint16_t); // pack sequence numbers +printf("\t\t packed %d seq #s:", numSequenceNumbers); for (int i = 0; i < numSequenceNumbers; i++) { OCTREE_PACKET_SEQUENCE* sequenceNumberAt = (OCTREE_PACKET_SEQUENCE*)dataAt; *sequenceNumberAt = stats.getNextSequenceNumberToNack(); dataAt += sizeof(OCTREE_PACKET_SEQUENCE); +printf(" %d,", *sequenceNumberAt); } +printf("\n"); _octreeSceneStatsLock.unlock(); diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index c0d7941edf..f9630c9102 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -271,6 +271,23 @@ qint64 LimitedNodeList::writeDatagram(const char* data, qint64 size, const Share return writeDatagram(QByteArray(data, size), destinationNode, overridenSockAddr); } +qint64 LimitedNodeList::writeDatagram2(int seq, const char* data, qint64 size, const SharedNodePointer& destinationNode, + const HifiSockAddr& overridenSockAddr) { + + qint64 ret; + + if (randFloat() < 0.8f) { + ret = writeDatagram(QByteArray(data, size), destinationNode, overridenSockAddr); + } + else { + printf("\t\t\t dropped packet seq = %d!!!\n", seq); + } + + + return ret; +} + + qint64 LimitedNodeList::writeUnverifiedDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode, const HifiSockAddr& overridenSockAddr) { return writeUnverifiedDatagram(QByteArray(data, size), destinationNode, overridenSockAddr); diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index a4bc8022bf..b3481885c8 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -72,6 +72,9 @@ public: qint64 writeDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode, const HifiSockAddr& overridenSockAddr = HifiSockAddr()); +qint64 writeDatagram2(int seq, const char* data, qint64 size, const SharedNodePointer& destinationNode, + const HifiSockAddr& overridenSockAddr = HifiSockAddr()); + qint64 writeUnverifiedDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode, const HifiSockAddr& overridenSockAddr = HifiSockAddr()); diff --git a/libraries/octree/src/OctreeSceneStats.cpp b/libraries/octree/src/OctreeSceneStats.cpp index 01332fbc46..a93b2d0374 100644 --- a/libraries/octree/src/OctreeSceneStats.cpp +++ b/libraries/octree/src/OctreeSceneStats.cpp @@ -159,7 +159,7 @@ void OctreeSceneStats::copyFromOther(const OctreeSceneStats& other) { _incomingPossibleDuplicate = other._incomingPossibleDuplicate; _missingSequenceNumbers = other._missingSequenceNumbers; -_missingSequenceNumbersToNack = other._missingSequenceNumbersToNack; +_sequenceNumbersToNack = other._sequenceNumbersToNack; } From b39559d86086f3b78fff66e5476553c315ba9a28 Mon Sep 17 00:00:00 2001 From: wangyix Date: Fri, 6 Jun 2014 17:44:30 -0700 Subject: [PATCH 07/18] packet recovery seems to be working Seems to impact FPS a lot. OctreeSceneStats is not being locked (causes freezing, need to find out why). --- .../src/octree/OctreeQueryNode.cpp | 5 --- .../src/octree/OctreeQueryNode.h | 4 ++- .../src/octree/OctreeSendThread.cpp | 3 +- assignment-client/src/octree/OctreeServer.cpp | 35 ++++++++++--------- interface/src/Application.cpp | 16 +++++---- libraries/networking/src/LimitedNodeList.cpp | 4 +-- libraries/networking/src/PacketHeaders.h | 3 +- 7 files changed, 37 insertions(+), 33 deletions(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index 208be5951b..cf01e9a864 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -377,11 +377,6 @@ void OctreeQueryNode::packetSent(const QByteArray& packet) { _sequenceNumber++; } - -void OctreeQueryNode::addSequenceNumbersToResend(const QList& sequenceNumbers) { - _nackedSequenceNumbers.append(sequenceNumbers); -} - bool OctreeQueryNode::hasNextNackedPacket() const { return !_nackedSequenceNumbers.isEmpty(); } diff --git a/assignment-client/src/octree/OctreeQueryNode.h b/assignment-client/src/octree/OctreeQueryNode.h index e1707cc899..b79367503c 100644 --- a/assignment-client/src/octree/OctreeQueryNode.h +++ b/assignment-client/src/octree/OctreeQueryNode.h @@ -109,7 +109,9 @@ public: OCTREE_PACKET_SEQUENCE getSequenceNumber() const { return _sequenceNumber; } - void addSequenceNumbersToResend(const QList& sequenceNumbers); + void addNackedSequenceNumber(OCTREE_PACKET_SEQUENCE sequenceNumber) { + _nackedSequenceNumbers.append(sequenceNumber); + } bool hasNextNackedPacket() const; const QByteArray* getNextNackedPacket(); diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index e5c47f5d2d..cb8a773a64 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -305,7 +305,8 @@ int OctreeSendThread::resendNackedPackets(OctreeQueryNode* nodeData) { _totalWastedBytes += MAX_PACKET_SIZE - packet->size(); // ??? } } - + +if (packetsSent > 0) printf("\t\t re-sent %d packets!\n", packetsSent); return packetsSent; } diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 46eb7aac16..8cf1649cdb 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -832,10 +832,9 @@ void OctreeServer::readPendingDatagrams() { PacketType packetType = packetTypeForPacket(receivedPacket); SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket); if (packetType == getMyQueryMessageType()) { - // If we got a query packet, then we're talking to an agent, and we // need to make sure we have it in our nodeList. - if (matchingNode) { + if (matchingNode) { nodeList->updateNodeWithDataFromPacket(matchingNode, receivedPacket); OctreeQueryNode* nodeData = (OctreeQueryNode*)matchingNode->getLinkedData(); if (nodeData && !nodeData->isOctreeSendThreadInitalized()) { @@ -852,25 +851,29 @@ void OctreeServer::readPendingDatagrams() { } else if (packetType == PacketTypeOctreeDataNack) { // parse packet for sequence numbers that need to be resent -int numBytesPacketHeader = numBytesForPacketHeader(receivedPacket); -const unsigned char* dataAt = reinterpret_cast(receivedPacket.data()) + numBytesPacketHeader; -uint16_t numSequenceNumbers = (*(uint16_t*)dataAt); -dataAt += sizeof(uint16_t); +if (matchingNode) { -// read sequence numbers -QList sequenceNumbers; -for (int i = 0; i < numSequenceNumbers; i++) { - OCTREE_PACKET_SEQUENCE sequenceNumber = (*(OCTREE_PACKET_SEQUENCE*)dataAt); - sequenceNumbers.append(sequenceNumber); - dataAt += sizeof(OCTREE_PACKET_SEQUENCE); + OctreeQueryNode* nodeData = (OctreeQueryNode*)matchingNode->getLinkedData(); -printf("\t\t\t nacked packet: seq = %d\n", sequenceNumber); + int numBytesPacketHeader = numBytesForPacketHeader(receivedPacket); + const unsigned char* dataAt = reinterpret_cast(receivedPacket.data()) + numBytesPacketHeader; + + uint16_t numSequenceNumbers = (*(uint16_t*)dataAt); + dataAt += sizeof(uint16_t); + +printf("\t received nack packet containing %d seq nums\n", numSequenceNumbers); + + // read sequence numbers + for (int i = 0; i < numSequenceNumbers; i++) { + OCTREE_PACKET_SEQUENCE sequenceNumber = (*(OCTREE_PACKET_SEQUENCE*)dataAt); + nodeData->addNackedSequenceNumber(sequenceNumber); + dataAt += sizeof(OCTREE_PACKET_SEQUENCE); + +printf("\t seq = %d\n", sequenceNumber); + } } -OctreeQueryNode* nodeData = (OctreeQueryNode*)matchingNode->getLinkedData(); // move this or something -nodeData->addSequenceNumbersToResend(sequenceNumbers); - } else if (packetType == PacketTypeJurisdictionRequest) { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 07bef852f2..a28343eb96 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2110,8 +2110,6 @@ void Application::updateMyAvatar(float deltaTime) { void Application::sendNack() { -printf("\n\t sendNack()...\n"); - char packet[MAX_PACKET_SIZE]; NodeList* nodeList = NodeList::getInstance(); @@ -2124,15 +2122,18 @@ printf("\n\t sendNack()...\n"); || node->getType() == NodeType::ModelServer) ) { - _octreeSceneStatsLock.lockForWrite(); + //_octreeSceneStatsLock.lockForWrite(); OctreeSceneStats& stats = _octreeServerSceneStats[node->getUUID()]; + int numSequenceNumbersAvailable = stats.getNumSequenceNumbersToNack(); + if (numSequenceNumbersAvailable == 0) + continue; char* dataAt = packet; int bytesRemaining = MAX_PACKET_SIZE; // pack header - int numBytesPacketHeader = populatePacketHeader(packet, PacketTypeOctreeDataNack, node->getUUID()); + int numBytesPacketHeader = populatePacketHeader(packet, PacketTypeOctreeDataNack); dataAt += numBytesPacketHeader; bytesRemaining -= numBytesPacketHeader; @@ -2140,12 +2141,13 @@ printf("\n\t sendNack()...\n"); // calculate and pack number of sequence numbers - uint16_t numSequenceNumbers = min(stats.getNumSequenceNumbersToNack(), numPacketsRoomFor); + uint16_t numSequenceNumbers = min(numSequenceNumbersAvailable, numPacketsRoomFor); uint16_t* numSequenceNumbersAt = (uint16_t*)dataAt; *numSequenceNumbersAt = numSequenceNumbers; dataAt += sizeof(uint16_t); // pack sequence numbers +printf("\n\t sending nack...\n"); printf("\t\t packed %d seq #s:", numSequenceNumbers); for (int i = 0; i < numSequenceNumbers; i++) { OCTREE_PACKET_SEQUENCE* sequenceNumberAt = (OCTREE_PACKET_SEQUENCE*)dataAt; @@ -2155,10 +2157,10 @@ printf(" %d,", *sequenceNumberAt); } printf("\n"); - _octreeSceneStatsLock.unlock(); + //_octreeSceneStatsLock.unlock(); // make sure we still have an active socket???? - nodeList->writeUnverifiedDatagram(packet, dataAt - packet, node); + nodeList->writeUnverifiedDatagram(packet, dataAt-packet, node); } } } diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index f9630c9102..15cebc26ac 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -274,13 +274,13 @@ qint64 LimitedNodeList::writeDatagram(const char* data, qint64 size, const Share qint64 LimitedNodeList::writeDatagram2(int seq, const char* data, qint64 size, const SharedNodePointer& destinationNode, const HifiSockAddr& overridenSockAddr) { - qint64 ret; + qint64 ret = -1; if (randFloat() < 0.8f) { ret = writeDatagram(QByteArray(data, size), destinationNode, overridenSockAddr); } else { - printf("\t\t\t dropped packet seq = %d!!!\n", seq); + printf("dropped packet seq = %d --------------------------\n", seq); } diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index a73ffe8564..eac2f88870 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -75,7 +75,8 @@ const QSet NON_VERIFIED_PACKETS = QSet() << PacketTypeDomainServerRequireDTLS << PacketTypeDomainConnectRequest << PacketTypeDomainList << PacketTypeDomainListRequest << PacketTypeDomainOAuthRequest << PacketTypeCreateAssignment << PacketTypeRequestAssignment << PacketTypeStunResponse - << PacketTypeNodeJsonStats << PacketTypeVoxelQuery << PacketTypeParticleQuery << PacketTypeModelQuery; + << PacketTypeNodeJsonStats << PacketTypeVoxelQuery << PacketTypeParticleQuery << PacketTypeModelQuery +<< PacketTypeOctreeDataNack; const int NUM_BYTES_MD5_HASH = 16; const int NUM_STATIC_HEADER_BYTES = sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID; From 52860908128fe0052a18981ace38b2ec06da2a46 Mon Sep 17 00:00:00 2001 From: wangyix Date: Fri, 6 Jun 2014 17:52:48 -0700 Subject: [PATCH 08/18] removed interface print statements --- interface/src/Application.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a28343eb96..87e82b21a2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2147,15 +2147,15 @@ void Application::sendNack() { dataAt += sizeof(uint16_t); // pack sequence numbers -printf("\n\t sending nack...\n"); -printf("\t\t packed %d seq #s:", numSequenceNumbers); +//printf("\n\t sending nack...\n"); +//printf("\t\t packed %d seq #s:", numSequenceNumbers); for (int i = 0; i < numSequenceNumbers; i++) { OCTREE_PACKET_SEQUENCE* sequenceNumberAt = (OCTREE_PACKET_SEQUENCE*)dataAt; *sequenceNumberAt = stats.getNextSequenceNumberToNack(); dataAt += sizeof(OCTREE_PACKET_SEQUENCE); -printf(" %d,", *sequenceNumberAt); +//printf(" %d,", *sequenceNumberAt); } -printf("\n"); +//printf("\n"); //_octreeSceneStatsLock.unlock(); From 3bc457d4d2ea981f3c12bb8605bfe078f9c180bf Mon Sep 17 00:00:00 2001 From: wangyix Date: Mon, 9 Jun 2014 11:14:02 -0700 Subject: [PATCH 09/18] added octree scene stats locking and unlocking --- .../src/octree/OctreeQueryNode.cpp | 8 +-- .../src/octree/OctreeSendThread.cpp | 3 - interface/src/Application.cpp | 69 ++++++++++++------- libraries/octree/src/OctreeSceneStats.h | 4 +- 4 files changed, 49 insertions(+), 35 deletions(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index cf01e9a864..5cfe5501e1 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -382,11 +382,9 @@ bool OctreeQueryNode::hasNextNackedPacket() const { } const QByteArray* OctreeQueryNode::getNextNackedPacket() { - if (!_nackedSequenceNumbers.isEmpty()) { - const QByteArray* nextPacket = _sentPacketHistory.getPacket(_nackedSequenceNumbers.first()); - _nackedSequenceNumbers.pop_front(); - return nextPacket; // could be null + // could return null if packet is not in the history + return _sentPacketHistory.getPacket(_nackedSequenceNumbers.takeFirst()); } return NULL; -} \ No newline at end of file +} diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index cb8a773a64..6f39cd28dc 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -288,18 +288,15 @@ NodeList::getInstance()->writeDatagram2(nodeData->getSequenceNumber(), (char*)no int OctreeSendThread::resendNackedPackets(OctreeQueryNode* nodeData) { const int MAX_PACKETS_RESEND = 10; - int packetsSent = 0; const QByteArray* packet; while (nodeData->hasNextNackedPacket() && packetsSent < MAX_PACKETS_RESEND) { packet = nodeData->getNextNackedPacket(); - // packet will be NULL if it's not in nodeData's packet history if (packet) { NodeList::getInstance()->writeDatagram(*packet, _node); packetsSent++; - // ?????? _totalBytes += packet->size(); _totalPackets++; _totalWastedBytes += MAX_PACKET_SIZE - packet->size(); // ??? diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 87e82b21a2..f8152bb62b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2107,6 +2107,21 @@ void Application::updateMyAvatar(float deltaTime) { } } +/*/ Attempt to identify the sender from it's address. + if (sendingNode) { + QUuid nodeUUID = sendingNode->getUUID(); + + // now that we know the node ID, let's add these stats to the stats for that node... + _octreeSceneStatsLock.lockForWrite(); + if (_octreeServerSceneStats.find(nodeUUID) != _octreeServerSceneStats.end()) { + OctreeSceneStats& stats = _octreeServerSceneStats[nodeUUID]; + stats.trackIncomingOctreePacket(packet, wasStatsPacket, sendingNode->getClockSkewUsec()); + } + _octreeSceneStatsLock.unlock(); + } + */ + + void Application::sendNack() { @@ -2122,13 +2137,6 @@ void Application::sendNack() { || node->getType() == NodeType::ModelServer) ) { - //_octreeSceneStatsLock.lockForWrite(); - - OctreeSceneStats& stats = _octreeServerSceneStats[node->getUUID()]; - int numSequenceNumbersAvailable = stats.getNumSequenceNumbersToNack(); - if (numSequenceNumbersAvailable == 0) - continue; - char* dataAt = packet; int bytesRemaining = MAX_PACKET_SIZE; @@ -2136,28 +2144,39 @@ void Application::sendNack() { int numBytesPacketHeader = populatePacketHeader(packet, PacketTypeOctreeDataNack); dataAt += numBytesPacketHeader; bytesRemaining -= numBytesPacketHeader; - - int numPacketsRoomFor = (bytesRemaining - sizeof(uint16_t)) / sizeof(OCTREE_PACKET_SEQUENCE); + int numSequenceNumbersRoomFor = (bytesRemaining - sizeof(uint16_t)) / sizeof(OCTREE_PACKET_SEQUENCE); - // calculate and pack number of sequence numbers - uint16_t numSequenceNumbers = min(numSequenceNumbersAvailable, numPacketsRoomFor); - uint16_t* numSequenceNumbersAt = (uint16_t*)dataAt; - *numSequenceNumbersAt = numSequenceNumbers; - dataAt += sizeof(uint16_t); + QUuid nodeUUID = node->getUUID(); - // pack sequence numbers -//printf("\n\t sending nack...\n"); -//printf("\t\t packed %d seq #s:", numSequenceNumbers); - for (int i = 0; i < numSequenceNumbers; i++) { - OCTREE_PACKET_SEQUENCE* sequenceNumberAt = (OCTREE_PACKET_SEQUENCE*)dataAt; - *sequenceNumberAt = stats.getNextSequenceNumberToNack(); - dataAt += sizeof(OCTREE_PACKET_SEQUENCE); -//printf(" %d,", *sequenceNumberAt); + _octreeSceneStatsLock.lockForWrite(); + if (_octreeServerSceneStats.find(nodeUUID) != _octreeServerSceneStats.end()) { + OctreeSceneStats& stats = _octreeServerSceneStats[nodeUUID]; + + int numSequenceNumbersAvailable = stats.getNumSequenceNumbersToNack(); + if (numSequenceNumbersAvailable == 0) { + _octreeSceneStatsLock.unlock(); + continue; + } + + // calculate and pack number of sequence numbers + uint16_t numSequenceNumbers = min(numSequenceNumbersAvailable, numSequenceNumbersRoomFor); + uint16_t* numSequenceNumbersAt = (uint16_t*)dataAt; + *numSequenceNumbersAt = numSequenceNumbers; + dataAt += sizeof(uint16_t); + + // pack sequence numbers + //printf("\n\t sending nack...\n"); + //printf("\t\t packed %d seq #s:", numSequenceNumbers); + for (int i = 0; i < numSequenceNumbers; i++) { + OCTREE_PACKET_SEQUENCE* sequenceNumberAt = (OCTREE_PACKET_SEQUENCE*)dataAt; + *sequenceNumberAt = stats.getNextSequenceNumberToNack(); + dataAt += sizeof(OCTREE_PACKET_SEQUENCE); + //printf(" %d,", *sequenceNumberAt); + } + //printf("\n"); } -//printf("\n"); - - //_octreeSceneStatsLock.unlock(); + _octreeSceneStatsLock.unlock(); // make sure we still have an active socket???? nodeList->writeUnverifiedDatagram(packet, dataAt-packet, node); diff --git a/libraries/octree/src/OctreeSceneStats.h b/libraries/octree/src/OctreeSceneStats.h index ca9bf7c74b..ac9b1606c1 100644 --- a/libraries/octree/src/OctreeSceneStats.h +++ b/libraries/octree/src/OctreeSceneStats.h @@ -275,8 +275,8 @@ private: quint32 _incomingLate; /// out of order later than expected quint32 _incomingReallyLate; /// out of order and later than MAX_MISSING_SEQUENCE_OLD_AGE late quint32 _incomingPossibleDuplicate; /// out of order possibly a duplicate - QSet _missingSequenceNumbers; -QSet _sequenceNumbersToNack; + QSet _missingSequenceNumbers; +QSet _sequenceNumbersToNack; SimpleMovingAverage _incomingFlightTimeAverage; // features related items From 936f04cececd2e29177d9189f25487e623ff7240 Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Mon, 9 Jun 2014 11:55:29 -0700 Subject: [PATCH 10/18] Simple raypicking for scripts with oculus rift. --- interface/src/Camera.cpp | 8 +++++++- interface/src/ui/ApplicationOverlay.cpp | 21 +++++++++++++++++++-- interface/src/ui/ApplicationOverlay.h | 3 ++- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index f9ee5bdd25..0e33e14f32 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -18,6 +18,7 @@ #include "Camera.h" #include "Menu.h" #include "Util.h" +#include "devices/OculusManager.h" const float CAMERA_FIRST_PERSON_MODE_UP_SHIFT = 0.0f; const float CAMERA_FIRST_PERSON_MODE_DISTANCE = 0.0f; @@ -264,7 +265,12 @@ PickRay CameraScriptableObject::computePickRay(float x, float y) { float screenWidth = Application::getInstance()->getGLWidget()->width(); float screenHeight = Application::getInstance()->getGLWidget()->height(); PickRay result; - _viewFrustum->computePickRay(x / screenWidth, y / screenHeight, result.origin, result.direction); + if (OculusManager::isConnected()) { + result.origin = _camera->getPosition(); + Application::getInstance()->getApplicationOverlay().computeOculusPickRay(x / screenWidth, y / screenHeight, result.direction); + } else { + _viewFrustum->computePickRay(x / screenWidth, y / screenHeight, result.origin, result.direction); + } return result; } diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 49ec8ecddb..f5de7459a8 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -297,6 +297,25 @@ void ApplicationOverlay::displayOverlayTexture(Camera& whichCamera) { glDisable(GL_TEXTURE_2D); } +const float textureFov = PI / 2.5f; + +void ApplicationOverlay::computeOculusPickRay(float x, float y, glm::vec3& direction) const { + glm::quat rot = Application::getInstance()->getAvatar()->getOrientation(); + + //invert y direction + y = 1.0 - y; + + //Get position on hemisphere UI + x = sin((x - 0.5f) * textureFov); + y = sin((y - 0.5f) * textureFov); + + float dist = sqrt(x * x + y * y); + float z = -sqrt(1.0f - dist * dist); + + //Rotate the UI pick ray by the avatar orientation + direction = glm::normalize(rot * glm::vec3(x, y, z)); +} + // Fast helper functions inline float max(float a, float b) { return (a > b) ? a : b; @@ -306,8 +325,6 @@ inline float min(float a, float b) { return (a < b) ? a : b; } -const float textureFov = PI / 2.5f; - // Draws the FBO texture for Oculus rift. TODO: Draw a curved texture instead of plane. void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index 8817549277..1bf0e18816 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -15,7 +15,7 @@ class Overlays; class QOpenGLFramebufferObject; -// Handles the drawing of the overlays to the scree +// Handles the drawing of the overlays to the screen class ApplicationOverlay { public: @@ -27,6 +27,7 @@ public: void renderOverlay(bool renderToTexture = false); void displayOverlayTexture(Camera& whichCamera); void displayOverlayTextureOculus(Camera& whichCamera); + void computeOculusPickRay(float x, float y, glm::vec3& direction) const; // Getters QOpenGLFramebufferObject* getFramebufferObject(); From 529dd827a2d613aa6c6b3fd74d9dfcbeaf9de72e Mon Sep 17 00:00:00 2001 From: wangyix Date: Mon, 9 Jun 2014 12:00:19 -0700 Subject: [PATCH 11/18] moved around code in sendNack() a bit --- interface/src/Application.cpp | 65 ++++++++++++---------- libraries/networking/src/PacketHeaders.cpp | 2 +- libraries/octree/src/OctreeSceneStats.h | 4 +- 3 files changed, 38 insertions(+), 33 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f8152bb62b..3ebfe728de 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2137,6 +2137,25 @@ void Application::sendNack() { || node->getType() == NodeType::ModelServer) ) { + QUuid nodeUUID = node->getUUID(); + + + _octreeSceneStatsLock.lockForWrite(); + + // retreive octree scene stats of this node + if (_octreeServerSceneStats.find(nodeUUID) == _octreeServerSceneStats.end()) { + _octreeSceneStatsLock.unlock(); + continue; + } + OctreeSceneStats& stats = _octreeServerSceneStats[nodeUUID]; + + // check if there are any sequence numbers that need to be nacked + int numSequenceNumbersAvailable = stats.getNumSequenceNumbersToNack(); + if (numSequenceNumbersAvailable == 0) { + _octreeSceneStatsLock.unlock(); + continue; + } + char* dataAt = packet; int bytesRemaining = MAX_PACKET_SIZE; @@ -2146,40 +2165,26 @@ void Application::sendNack() { bytesRemaining -= numBytesPacketHeader; int numSequenceNumbersRoomFor = (bytesRemaining - sizeof(uint16_t)) / sizeof(OCTREE_PACKET_SEQUENCE); + // calculate and pack the number of sequence numbers + uint16_t numSequenceNumbers = min(numSequenceNumbersAvailable, numSequenceNumbersRoomFor); + uint16_t* numSequenceNumbersAt = (uint16_t*)dataAt; + *numSequenceNumbersAt = numSequenceNumbers; + dataAt += sizeof(uint16_t); - QUuid nodeUUID = node->getUUID(); - - _octreeSceneStatsLock.lockForWrite(); - if (_octreeServerSceneStats.find(nodeUUID) != _octreeServerSceneStats.end()) { - OctreeSceneStats& stats = _octreeServerSceneStats[nodeUUID]; - - int numSequenceNumbersAvailable = stats.getNumSequenceNumbersToNack(); - if (numSequenceNumbersAvailable == 0) { - _octreeSceneStatsLock.unlock(); - continue; - } - - // calculate and pack number of sequence numbers - uint16_t numSequenceNumbers = min(numSequenceNumbersAvailable, numSequenceNumbersRoomFor); - uint16_t* numSequenceNumbersAt = (uint16_t*)dataAt; - *numSequenceNumbersAt = numSequenceNumbers; - dataAt += sizeof(uint16_t); - - // pack sequence numbers - //printf("\n\t sending nack...\n"); - //printf("\t\t packed %d seq #s:", numSequenceNumbers); - for (int i = 0; i < numSequenceNumbers; i++) { - OCTREE_PACKET_SEQUENCE* sequenceNumberAt = (OCTREE_PACKET_SEQUENCE*)dataAt; - *sequenceNumberAt = stats.getNextSequenceNumberToNack(); - dataAt += sizeof(OCTREE_PACKET_SEQUENCE); - //printf(" %d,", *sequenceNumberAt); - } - //printf("\n"); + // pack sequence numbers +//printf("\n\t sending nack...\n"); +//printf("\t\t packed %d seq #s:", numSequenceNumbers); + for (int i = 0; i < numSequenceNumbers; i++) { + OCTREE_PACKET_SEQUENCE* sequenceNumberAt = (OCTREE_PACKET_SEQUENCE*)dataAt; + *sequenceNumberAt = stats.getNextSequenceNumberToNack(); + dataAt += sizeof(OCTREE_PACKET_SEQUENCE); +//printf(" %d,", *sequenceNumberAt); } +//printf("\n"); + _octreeSceneStatsLock.unlock(); - // make sure we still have an active socket???? - nodeList->writeUnverifiedDatagram(packet, dataAt-packet, node); + nodeList->writeUnverifiedDatagram(packet, dataAt - packet, node); } } } diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 7278f1fbcb..e2bc46b3be 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -108,7 +108,7 @@ int populatePacketHeader(char* packet, PacketType type, const QUuid& connectionU position += NUM_BYTES_RFC4122_UUID; if (!NON_VERIFIED_PACKETS.contains(type)) { - // pack 16 bytes of zeros where the md5 hash will be placed one 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); position += NUM_BYTES_MD5_HASH; } diff --git a/libraries/octree/src/OctreeSceneStats.h b/libraries/octree/src/OctreeSceneStats.h index ac9b1606c1..ca9bf7c74b 100644 --- a/libraries/octree/src/OctreeSceneStats.h +++ b/libraries/octree/src/OctreeSceneStats.h @@ -275,8 +275,8 @@ private: quint32 _incomingLate; /// out of order later than expected quint32 _incomingReallyLate; /// out of order and later than MAX_MISSING_SEQUENCE_OLD_AGE late quint32 _incomingPossibleDuplicate; /// out of order possibly a duplicate - QSet _missingSequenceNumbers; -QSet _sequenceNumbersToNack; + QSet _missingSequenceNumbers; +QSet _sequenceNumbersToNack; SimpleMovingAverage _incomingFlightTimeAverage; // features related items From aa694d69678d94c71d3961de068e5bf0d1a4c562 Mon Sep 17 00:00:00 2001 From: wangyix Date: Mon, 9 Jun 2014 12:35:26 -0700 Subject: [PATCH 12/18] removed debug code --- .../src/octree/OctreeQueryNode.cpp | 20 +++++++++ .../src/octree/OctreeQueryNode.h | 11 ++--- .../src/octree/OctreeSendThread.cpp | 22 +++------- .../src/octree/OctreeSendThread.h | 2 +- assignment-client/src/octree/OctreeServer.cpp | 36 ++++------------ .../src/octree/SentPacketHistory.cpp | 5 ++- .../src/octree/SentPacketHistory.h | 1 - interface/src/Application.cpp | 42 ++++--------------- interface/src/Application.h | 4 +- libraries/networking/src/LimitedNodeList.cpp | 17 -------- libraries/networking/src/LimitedNodeList.h | 3 -- libraries/networking/src/PacketHeaders.h | 2 +- libraries/octree/src/OctreeSceneStats.cpp | 12 +++--- libraries/octree/src/OctreeSceneStats.h | 9 ++-- 14 files changed, 64 insertions(+), 122 deletions(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index 5cfe5501e1..f8b5e34472 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -388,3 +388,23 @@ const QByteArray* OctreeQueryNode::getNextNackedPacket() { } return NULL; } + +void OctreeQueryNode::parseNackPacket(QByteArray& packet) { + + int numBytesPacketHeader = numBytesForPacketHeader(packet); + const unsigned char* dataAt = reinterpret_cast(packet.data()) + numBytesPacketHeader; + + uint16_t numSequenceNumbers = (*(uint16_t*)dataAt); + dataAt += sizeof(uint16_t); + + printf("\t received nack packet containing %d seq nums\n", numSequenceNumbers); + + // read sequence numbers + for (int i = 0; i < numSequenceNumbers; i++) { + OCTREE_PACKET_SEQUENCE sequenceNumber = (*(OCTREE_PACKET_SEQUENCE*)dataAt); + _nackedSequenceNumbers.enqueue(sequenceNumber); + dataAt += sizeof(OCTREE_PACKET_SEQUENCE); + + printf("\t seq = %d\n", sequenceNumber); + } +} diff --git a/assignment-client/src/octree/OctreeQueryNode.h b/assignment-client/src/octree/OctreeQueryNode.h index b79367503c..d955d3fdf7 100644 --- a/assignment-client/src/octree/OctreeQueryNode.h +++ b/assignment-client/src/octree/OctreeQueryNode.h @@ -24,8 +24,7 @@ #include #include // for SharedAssignmentPointer #include "SentPacketHistory.h" - -#include // i added dis +#include class OctreeSendThread; @@ -109,9 +108,7 @@ public: OCTREE_PACKET_SEQUENCE getSequenceNumber() const { return _sequenceNumber; } - void addNackedSequenceNumber(OCTREE_PACKET_SEQUENCE sequenceNumber) { - _nackedSequenceNumbers.append(sequenceNumber); - } + void parseNackPacket(QByteArray& packet); bool hasNextNackedPacket() const; const QByteArray* getNextNackedPacket(); @@ -158,8 +155,8 @@ private: PacketType _myPacketType; bool _isShuttingDown; -SentPacketHistory _sentPacketHistory; -QQueue _nackedSequenceNumbers; + SentPacketHistory _sentPacketHistory; + QQueue _nackedSequenceNumbers; }; #endif // hifi_OctreeQueryNode_h diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 6f39cd28dc..30e3011ae8 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -85,7 +85,7 @@ bool OctreeSendThread::process() { if (nodeData && !nodeData->isShuttingDown()) { bool viewFrustumChanged = nodeData->updateCurrentViewFrustum(); packetDistributor(nodeData, viewFrustumChanged); -resendNackedPackets(nodeData); + resendNackedPackets(nodeData); } } } @@ -181,7 +181,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes // actually send it OctreeServer::didCallWriteDatagram(this); -NodeList::getInstance()->writeDatagram2(nodeData->getSequenceNumber(), (char*) statsMessage, statsMessageLength, _node); + NodeList::getInstance()->writeDatagram((char*) statsMessage, statsMessageLength, _node); packetSent = true; } else { // not enough room in the packet, send two packets @@ -215,7 +215,7 @@ NodeList::getInstance()->writeDatagram2(nodeData->getSequenceNumber(), (char*) s packetsSent++; OctreeServer::didCallWriteDatagram(this); -NodeList::getInstance()->writeDatagram2(nodeData->getSequenceNumber(), (char*)nodeData->getPacket(), nodeData->getPacketLength(), _node); + NodeList::getInstance()->writeDatagram((char*)nodeData->getPacket(), nodeData->getPacketLength(), _node); packetSent = true; thisWastedBytes = MAX_PACKET_SIZE - nodeData->getPacketLength(); @@ -244,7 +244,7 @@ NodeList::getInstance()->writeDatagram2(nodeData->getSequenceNumber(), (char*)no if (nodeData->isPacketWaiting() && !nodeData->isShuttingDown()) { // just send the voxel packet OctreeServer::didCallWriteDatagram(this); -NodeList::getInstance()->writeDatagram2(nodeData->getSequenceNumber(), (char*)nodeData->getPacket(), nodeData->getPacketLength(), _node); + NodeList::getInstance()->writeDatagram((char*)nodeData->getPacket(), nodeData->getPacketLength(), _node); packetSent = true; int thisWastedBytes = MAX_PACKET_SIZE - nodeData->getPacketLength(); @@ -281,10 +281,6 @@ NodeList::getInstance()->writeDatagram2(nodeData->getSequenceNumber(), (char*)no return packetsSent; } - - - - int OctreeSendThread::resendNackedPackets(OctreeQueryNode* nodeData) { const int MAX_PACKETS_RESEND = 10; @@ -299,20 +295,12 @@ int OctreeSendThread::resendNackedPackets(OctreeQueryNode* nodeData) { _totalBytes += packet->size(); _totalPackets++; - _totalWastedBytes += MAX_PACKET_SIZE - packet->size(); // ??? + _totalWastedBytes += MAX_PACKET_SIZE - packet->size(); } } - -if (packetsSent > 0) -printf("\t\t re-sent %d packets!\n", packetsSent); return packetsSent; } - - - - - /// Version of voxel distributor that sends the deepest LOD level at once int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrustumChanged) { diff --git a/assignment-client/src/octree/OctreeSendThread.h b/assignment-client/src/octree/OctreeSendThread.h index cc0cdac3ad..e7599ebcd2 100644 --- a/assignment-client/src/octree/OctreeSendThread.h +++ b/assignment-client/src/octree/OctreeSendThread.h @@ -56,7 +56,7 @@ private: int _nodeMissingCount; bool _isShuttingDown; -int resendNackedPackets(OctreeQueryNode* nodeData); + int resendNackedPackets(OctreeQueryNode* nodeData); }; diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 8cf1649cdb..9d3402b895 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -849,33 +849,15 @@ void OctreeServer::readPendingDatagrams() { } } else if (packetType == PacketTypeOctreeDataNack) { - -// parse packet for sequence numbers that need to be resent - -if (matchingNode) { - - OctreeQueryNode* nodeData = (OctreeQueryNode*)matchingNode->getLinkedData(); - - int numBytesPacketHeader = numBytesForPacketHeader(receivedPacket); - const unsigned char* dataAt = reinterpret_cast(receivedPacket.data()) + numBytesPacketHeader; - - uint16_t numSequenceNumbers = (*(uint16_t*)dataAt); - dataAt += sizeof(uint16_t); - -printf("\t received nack packet containing %d seq nums\n", numSequenceNumbers); - - // read sequence numbers - for (int i = 0; i < numSequenceNumbers; i++) { - OCTREE_PACKET_SEQUENCE sequenceNumber = (*(OCTREE_PACKET_SEQUENCE*)dataAt); - nodeData->addNackedSequenceNumber(sequenceNumber); - dataAt += sizeof(OCTREE_PACKET_SEQUENCE); - -printf("\t seq = %d\n", sequenceNumber); - } -} - - - + // If we got a nack packet, then we're talking to an agent, and we + // need to make sure we have it in our nodeList. + if (matchingNode) { + nodeList->updateNodeWithDataFromPacket(matchingNode, receivedPacket); + OctreeQueryNode* nodeData = (OctreeQueryNode*)matchingNode->getLinkedData(); + if (nodeData) { + nodeData->parseNackPacket(receivedPacket); + } + } } else if (packetType == PacketTypeJurisdictionRequest) { _jurisdictionSender->queueReceivedPacket(matchingNode, receivedPacket); } else if (_octreeInboundPacketProcessor && getOctree()->handlesEditPacketType(packetType)) { diff --git a/assignment-client/src/octree/SentPacketHistory.cpp b/assignment-client/src/octree/SentPacketHistory.cpp index 0de163a23d..751e46e786 100644 --- a/assignment-client/src/octree/SentPacketHistory.cpp +++ b/assignment-client/src/octree/SentPacketHistory.cpp @@ -21,7 +21,8 @@ SentPacketHistory::SentPacketHistory(int size) void SentPacketHistory::packetSent(OCTREE_PACKET_SEQUENCE sequenceNumber, const QByteArray& packet) { _newestSequenceNumber = sequenceNumber; - // increment _newestPacketAt cyclically, insert new packet there + // increment _newestPacketAt cyclically, insert new packet there. + // this will overwrite the oldest packet in the buffer _newestPacketAt = (_newestPacketAt == _sentPackets.size() - 1) ? 0 : _newestPacketAt + 1; _sentPackets[_newestPacketAt] = packet; @@ -42,4 +43,4 @@ const QByteArray* SentPacketHistory::getPacket(OCTREE_PACKET_SEQUENCE sequenceNu if (packetAt < 0) { packetAt += _sentPackets.size(); } return &_sentPackets.at(packetAt); -} \ No newline at end of file +} diff --git a/assignment-client/src/octree/SentPacketHistory.h b/assignment-client/src/octree/SentPacketHistory.h index cbc50bc73c..4231400ac1 100644 --- a/assignment-client/src/octree/SentPacketHistory.h +++ b/assignment-client/src/octree/SentPacketHistory.h @@ -25,7 +25,6 @@ public: const QByteArray* getPacket(OCTREE_PACKET_SEQUENCE sequenceNumber) const; private: - QVector _sentPackets; // circular buffer int _newestPacketAt; int _numExistingPackets; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3ebfe728de..18a8d3ba12 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2095,33 +2095,17 @@ void Application::updateMyAvatar(float deltaTime) { } } -// sent a nack packet containing missing sequence numbers of received packets -{ - quint64 now = usecTimestampNow(); - quint64 sinceLastNack = now - _lastNackTime; - const quint64 TOO_LONG_SINCE_LAST_NACK = 250 * MSECS_PER_SECOND; - if (sinceLastNack > TOO_LONG_SINCE_LAST_NACK) { - _lastNackTime = now; - sendNack(); - } -} -} - -/*/ Attempt to identify the sender from it's address. - if (sendingNode) { - QUuid nodeUUID = sendingNode->getUUID(); - - // now that we know the node ID, let's add these stats to the stats for that node... - _octreeSceneStatsLock.lockForWrite(); - if (_octreeServerSceneStats.find(nodeUUID) != _octreeServerSceneStats.end()) { - OctreeSceneStats& stats = _octreeServerSceneStats[nodeUUID]; - stats.trackIncomingOctreePacket(packet, wasStatsPacket, sendingNode->getClockSkewUsec()); + // sent a nack packet containing missing sequence numbers of received packets + { + quint64 now = usecTimestampNow(); + quint64 sinceLastNack = now - _lastNackTime; + const quint64 TOO_LONG_SINCE_LAST_NACK = 250 * MSECS_PER_SECOND; + if (sinceLastNack > TOO_LONG_SINCE_LAST_NACK) { + _lastNackTime = now; + sendNack(); } - _octreeSceneStatsLock.unlock(); } - */ - - +} void Application::sendNack() { @@ -2139,7 +2123,6 @@ void Application::sendNack() { QUuid nodeUUID = node->getUUID(); - _octreeSceneStatsLock.lockForWrite(); // retreive octree scene stats of this node @@ -2172,15 +2155,11 @@ void Application::sendNack() { dataAt += sizeof(uint16_t); // pack sequence numbers -//printf("\n\t sending nack...\n"); -//printf("\t\t packed %d seq #s:", numSequenceNumbers); for (int i = 0; i < numSequenceNumbers; i++) { OCTREE_PACKET_SEQUENCE* sequenceNumberAt = (OCTREE_PACKET_SEQUENCE*)dataAt; *sequenceNumberAt = stats.getNextSequenceNumberToNack(); dataAt += sizeof(OCTREE_PACKET_SEQUENCE); -//printf(" %d,", *sequenceNumberAt); } -//printf("\n"); _octreeSceneStatsLock.unlock(); @@ -2189,9 +2168,6 @@ void Application::sendNack() { } } - - - void Application::queryOctree(NodeType_t serverType, PacketType packetType, NodeToJurisdictionMap& jurisdictions) { // if voxels are disabled, then don't send this at all... diff --git a/interface/src/Application.h b/interface/src/Application.h index 670ec35238..170be43493 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -413,8 +413,6 @@ private: void sendNack(); - - MainWindow* _window; GLCanvas* _glWidget; // our GLCanvas has a couple extra features @@ -585,7 +583,7 @@ private: QSystemTrayIcon* _trayIcon; -quint64 _lastNackTime; + quint64 _lastNackTime; }; #endif // hifi_Application_h diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 15cebc26ac..c0d7941edf 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -271,23 +271,6 @@ qint64 LimitedNodeList::writeDatagram(const char* data, qint64 size, const Share return writeDatagram(QByteArray(data, size), destinationNode, overridenSockAddr); } -qint64 LimitedNodeList::writeDatagram2(int seq, const char* data, qint64 size, const SharedNodePointer& destinationNode, - const HifiSockAddr& overridenSockAddr) { - - qint64 ret = -1; - - if (randFloat() < 0.8f) { - ret = writeDatagram(QByteArray(data, size), destinationNode, overridenSockAddr); - } - else { - printf("dropped packet seq = %d --------------------------\n", seq); - } - - - return ret; -} - - qint64 LimitedNodeList::writeUnverifiedDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode, const HifiSockAddr& overridenSockAddr) { return writeUnverifiedDatagram(QByteArray(data, size), destinationNode, overridenSockAddr); diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index b3481885c8..a4bc8022bf 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -72,9 +72,6 @@ public: qint64 writeDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode, const HifiSockAddr& overridenSockAddr = HifiSockAddr()); -qint64 writeDatagram2(int seq, const char* data, qint64 size, const SharedNodePointer& destinationNode, - const HifiSockAddr& overridenSockAddr = HifiSockAddr()); - qint64 writeUnverifiedDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode, const HifiSockAddr& overridenSockAddr = HifiSockAddr()); diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index eac2f88870..8ac5333d10 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -76,7 +76,7 @@ const QSet NON_VERIFIED_PACKETS = QSet() << PacketTypeDomainList << PacketTypeDomainListRequest << PacketTypeDomainOAuthRequest << PacketTypeCreateAssignment << PacketTypeRequestAssignment << PacketTypeStunResponse << PacketTypeNodeJsonStats << PacketTypeVoxelQuery << PacketTypeParticleQuery << PacketTypeModelQuery -<< PacketTypeOctreeDataNack; + << PacketTypeOctreeDataNack; const int NUM_BYTES_MD5_HASH = 16; const int NUM_STATIC_HEADER_BYTES = sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID; diff --git a/libraries/octree/src/OctreeSceneStats.cpp b/libraries/octree/src/OctreeSceneStats.cpp index a93b2d0374..868ef29886 100644 --- a/libraries/octree/src/OctreeSceneStats.cpp +++ b/libraries/octree/src/OctreeSceneStats.cpp @@ -46,7 +46,7 @@ OctreeSceneStats::OctreeSceneStats() : _incomingReallyLate(0), _incomingPossibleDuplicate(0), _missingSequenceNumbers(), -_sequenceNumbersToNack(), + _sequenceNumbersToNack(), _incomingFlightTimeAverage(samples), _jurisdictionRoot(NULL) { @@ -159,7 +159,7 @@ void OctreeSceneStats::copyFromOther(const OctreeSceneStats& other) { _incomingPossibleDuplicate = other._incomingPossibleDuplicate; _missingSequenceNumbers = other._missingSequenceNumbers; -_sequenceNumbersToNack = other._sequenceNumbersToNack; + _sequenceNumbersToNack = other._sequenceNumbersToNack; } @@ -928,7 +928,7 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, qDebug() << "found it in _missingSequenceNumbers"; } _missingSequenceNumbers.remove(sequence); -_sequenceNumbersToNack.remove(sequence); + _sequenceNumbersToNack.remove(sequence); _incomingLikelyLost--; _incomingRecovered++; } else { @@ -958,7 +958,7 @@ _sequenceNumbersToNack.remove(sequence); _incomingLikelyLost += missing; for(unsigned int missingSequence = expected; missingSequence < sequence; missingSequence++) { _missingSequenceNumbers << missingSequence; -_sequenceNumbersToNack << missingSequence; + _sequenceNumbersToNack << missingSequence; } } } @@ -986,7 +986,7 @@ _sequenceNumbersToNack << missingSequence; qDebug() << "pruning really old missing sequence:" << missingItem; } _missingSequenceNumbers.remove(missingItem); -_sequenceNumbersToNack.remove(missingItem); + _sequenceNumbersToNack.remove(missingItem); } } } @@ -1002,4 +1002,4 @@ uint16_t OctreeSceneStats::getNextSequenceNumberToNack() { uint16_t sequenceNumber = *it; _sequenceNumbersToNack.remove(sequenceNumber); return sequenceNumber; -} \ No newline at end of file +} diff --git a/libraries/octree/src/OctreeSceneStats.h b/libraries/octree/src/OctreeSceneStats.h index ca9bf7c74b..182bd6c86c 100644 --- a/libraries/octree/src/OctreeSceneStats.h +++ b/libraries/octree/src/OctreeSceneStats.h @@ -16,6 +16,7 @@ #include #include #include "JurisdictionMap.h" +#include "OctreePacketData.h" #define GREENISH 0x40ff40d0 #define YELLOWISH 0xffef40c0 @@ -172,8 +173,8 @@ public: quint32 getIncomingPossibleDuplicate() const { return _incomingPossibleDuplicate; } float getIncomingFlightTimeAverage() { return _incomingFlightTimeAverage.getAverage(); } -int getNumSequenceNumbersToNack() const; -uint16_t getNextSequenceNumberToNack(); + int getNumSequenceNumbersToNack() const; + OCTREE_PACKET_SEQUENCE getNextSequenceNumberToNack(); private: @@ -275,8 +276,8 @@ private: quint32 _incomingLate; /// out of order later than expected quint32 _incomingReallyLate; /// out of order and later than MAX_MISSING_SEQUENCE_OLD_AGE late quint32 _incomingPossibleDuplicate; /// out of order possibly a duplicate - QSet _missingSequenceNumbers; -QSet _sequenceNumbersToNack; + QSet _missingSequenceNumbers; + QSet _sequenceNumbersToNack; SimpleMovingAverage _incomingFlightTimeAverage; // features related items From 968ea3563caebf1ca080c62542ce32927135e98d Mon Sep 17 00:00:00 2001 From: wangyix Date: Mon, 9 Jun 2014 12:37:42 -0700 Subject: [PATCH 13/18] removed an extra space --- assignment-client/src/octree/OctreeServer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 9d3402b895..f51d65fcef 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -834,11 +834,11 @@ void OctreeServer::readPendingDatagrams() { if (packetType == getMyQueryMessageType()) { // If we got a query packet, then we're talking to an agent, and we // need to make sure we have it in our nodeList. - if (matchingNode) { + if (matchingNode) { nodeList->updateNodeWithDataFromPacket(matchingNode, receivedPacket); OctreeQueryNode* nodeData = (OctreeQueryNode*)matchingNode->getLinkedData(); if (nodeData && !nodeData->isOctreeSendThreadInitalized()) { - + // NOTE: this is an important aspect of the proper ref counting. The send threads/node data need to // know that the OctreeServer/Assignment will not get deleted on it while it's still active. The // solution is to get the shared pointer for the current assignment. We need to make sure this is the From 0fce7e721a5135b742b71bd418519743ca799cc5 Mon Sep 17 00:00:00 2001 From: wangyix Date: Mon, 9 Jun 2014 12:40:01 -0700 Subject: [PATCH 14/18] removed more spaces --- assignment-client/src/octree/SentPacketHistory.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/assignment-client/src/octree/SentPacketHistory.cpp b/assignment-client/src/octree/SentPacketHistory.cpp index 751e46e786..85e164bc41 100644 --- a/assignment-client/src/octree/SentPacketHistory.cpp +++ b/assignment-client/src/octree/SentPacketHistory.cpp @@ -20,12 +20,11 @@ SentPacketHistory::SentPacketHistory(int size) void SentPacketHistory::packetSent(OCTREE_PACKET_SEQUENCE sequenceNumber, const QByteArray& packet) { _newestSequenceNumber = sequenceNumber; - + // increment _newestPacketAt cyclically, insert new packet there. // this will overwrite the oldest packet in the buffer _newestPacketAt = (_newestPacketAt == _sentPackets.size() - 1) ? 0 : _newestPacketAt + 1; _sentPackets[_newestPacketAt] = packet; - if (_numExistingPackets < _sentPackets.size()) { _numExistingPackets++; } @@ -33,14 +32,11 @@ void SentPacketHistory::packetSent(OCTREE_PACKET_SEQUENCE sequenceNumber, const const QByteArray* SentPacketHistory::getPacket(OCTREE_PACKET_SEQUENCE sequenceNumber) const { - OCTREE_PACKET_SEQUENCE seqDiff = _newestSequenceNumber - sequenceNumber; if (!(seqDiff >= 0 && seqDiff < _numExistingPackets)) { return NULL; } - int packetAt = _newestPacketAt - seqDiff; if (packetAt < 0) { packetAt += _sentPackets.size(); } - return &_sentPackets.at(packetAt); } From 412d3e19fecab6dec650ae7842beddf5b282fc50 Mon Sep 17 00:00:00 2001 From: wangyix Date: Mon, 9 Jun 2014 12:56:00 -0700 Subject: [PATCH 15/18] removed debug prints in parseNackPacket() --- assignment-client/src/octree/OctreeQueryNode.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index f8b5e34472..372f15a76b 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -394,17 +394,14 @@ void OctreeQueryNode::parseNackPacket(QByteArray& packet) { int numBytesPacketHeader = numBytesForPacketHeader(packet); const unsigned char* dataAt = reinterpret_cast(packet.data()) + numBytesPacketHeader; + // read number of sequence numbers uint16_t numSequenceNumbers = (*(uint16_t*)dataAt); dataAt += sizeof(uint16_t); - printf("\t received nack packet containing %d seq nums\n", numSequenceNumbers); - // read sequence numbers for (int i = 0; i < numSequenceNumbers; i++) { OCTREE_PACKET_SEQUENCE sequenceNumber = (*(OCTREE_PACKET_SEQUENCE*)dataAt); _nackedSequenceNumbers.enqueue(sequenceNumber); dataAt += sizeof(OCTREE_PACKET_SEQUENCE); - - printf("\t seq = %d\n", sequenceNumber); } } From ff2a5342ee8f4208b465fabc2c925954b225e90b Mon Sep 17 00:00:00 2001 From: wangyix Date: Mon, 9 Jun 2014 12:57:50 -0700 Subject: [PATCH 16/18] removed another extra space --- assignment-client/src/octree/OctreeServer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index f51d65fcef..cb60f0816e 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -847,7 +847,6 @@ void OctreeServer::readPendingDatagrams() { nodeData->initializeOctreeSendThread(sharedAssignment, matchingNode); } } - } else if (packetType == PacketTypeOctreeDataNack) { // If we got a nack packet, then we're talking to an agent, and we // need to make sure we have it in our nodeList. From e45f2fed4b83b9014c5cfeb20c810fe04dde0239 Mon Sep 17 00:00:00 2001 From: wangyix Date: Mon, 9 Jun 2014 13:42:45 -0700 Subject: [PATCH 17/18] changed writelock to readlock plus a coding standard fix --- assignment-client/src/octree/SentPacketHistory.cpp | 4 +++- interface/src/Application.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/octree/SentPacketHistory.cpp b/assignment-client/src/octree/SentPacketHistory.cpp index 85e164bc41..0ea7fd8b69 100644 --- a/assignment-client/src/octree/SentPacketHistory.cpp +++ b/assignment-client/src/octree/SentPacketHistory.cpp @@ -37,6 +37,8 @@ const QByteArray* SentPacketHistory::getPacket(OCTREE_PACKET_SEQUENCE sequenceNu return NULL; } int packetAt = _newestPacketAt - seqDiff; - if (packetAt < 0) { packetAt += _sentPackets.size(); } + if (packetAt < 0) { + packetAt += _sentPackets.size(); + } return &_sentPackets.at(packetAt); } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 18a8d3ba12..574df09ee2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2123,7 +2123,7 @@ void Application::sendNack() { QUuid nodeUUID = node->getUUID(); - _octreeSceneStatsLock.lockForWrite(); + _octreeSceneStatsLock.lockForRead(); // retreive octree scene stats of this node if (_octreeServerSceneStats.find(nodeUUID) == _octreeServerSceneStats.end()) { From ee71d34f021ba90327ac96e1b9094c858679604f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 9 Jun 2014 14:03:47 -0700 Subject: [PATCH 18/18] add a crash guard around negative silent samples --- libraries/audio/src/PositionalAudioRingBuffer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/audio/src/PositionalAudioRingBuffer.cpp b/libraries/audio/src/PositionalAudioRingBuffer.cpp index 94a88897e3..bb47c6de9e 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.cpp +++ b/libraries/audio/src/PositionalAudioRingBuffer.cpp @@ -55,7 +55,9 @@ int PositionalAudioRingBuffer::parseData(const QByteArray& packet) { readBytes += sizeof(int16_t); - addSilentFrame(numSilentSamples); + if (numSilentSamples > 0) { + addSilentFrame(numSilentSamples); + } } else { // there is audio data to read readBytes += writeData(packet.data() + readBytes, packet.size() - readBytes);