diff --git a/interface/src/VoxelPacketProcessor.cpp b/interface/src/VoxelPacketProcessor.cpp index 011fb7f9ed..b2374bc711 100644 --- a/interface/src/VoxelPacketProcessor.cpp +++ b/interface/src/VoxelPacketProcessor.cpp @@ -48,6 +48,7 @@ void VoxelPacketProcessor::processPacket(sockaddr& senderAddress, unsigned char* return; // bail since piggyback data doesn't match our versioning } } else { + // Note... stats packets don't have sequence numbers, so we don't want to send those to trackIncomingVoxelPacket() return; // bail since no piggyback data } } // fall through to piggyback message diff --git a/libraries/voxel-server-library/src/VoxelNodeData.cpp b/libraries/voxel-server-library/src/VoxelNodeData.cpp index 6c18effa54..b7dec1053b 100644 --- a/libraries/voxel-server-library/src/VoxelNodeData.cpp +++ b/libraries/voxel-server-library/src/VoxelNodeData.cpp @@ -36,8 +36,7 @@ VoxelNodeData::VoxelNodeData(Node* owningNode) : _lastVoxelPacketLength = 0; _duplicatePacketCount = 0; _sequenceNumber = 0; - - resetVoxelPacket(); + resetVoxelPacket(true); // don't bump sequence } void VoxelNodeData::initializeVoxelSendThread(VoxelServer* voxelServer) { @@ -48,8 +47,11 @@ void VoxelNodeData::initializeVoxelSendThread(VoxelServer* voxelServer) { } bool VoxelNodeData::packetIsDuplicate() const { + // since our packets now include header information, like sequence number, and createTime, we can't just do a memcmp + // of the entire packet, we need to compare only the packet content... if (_lastVoxelPacketLength == getPacketLength()) { - return memcmp(_lastVoxelPacket, _voxelPacket, getPacketLength()) == 0; + return memcmp(_lastVoxelPacket + VOXEL_PACKET_HEADER_SIZE, + _voxelPacket+VOXEL_PACKET_HEADER_SIZE , getPacketLength() - VOXEL_PACKET_HEADER_SIZE) == 0; } return false; } @@ -88,7 +90,7 @@ bool VoxelNodeData::shouldSuppressDuplicatePacket() { return shouldSuppress; } -void VoxelNodeData::resetVoxelPacket() { +void VoxelNodeData::resetVoxelPacket(bool lastWasSurpressed) { // Whenever we call this, we will keep a copy of the last packet, so we can determine if the last packet has // changed since we last reset it. Since we know that no two packets can ever be identical without being the same // scene information, (e.g. the root node packet of a static scene), we can use this as a strategy for reducing @@ -124,7 +126,9 @@ void VoxelNodeData::resetVoxelPacket() { *sequenceAt = _sequenceNumber; _voxelPacketAt += sizeof(VOXEL_PACKET_SEQUENCE); _voxelPacketAvailableBytes -= sizeof(VOXEL_PACKET_SEQUENCE); - _sequenceNumber++; + if (!(lastWasSurpressed || _lastVoxelPacketLength == VOXEL_PACKET_HEADER_SIZE)) { + _sequenceNumber++; + } // pack in timestamp VOXEL_PACKET_SENT_TIME now = usecTimestampNow(); @@ -144,12 +148,12 @@ void VoxelNodeData::writeToPacket(const unsigned char* buffer, int bytes) { _voxelPacketAt += sizeof(VOXEL_PACKET_INTERNAL_SECTION_SIZE); _voxelPacketAvailableBytes -= sizeof(VOXEL_PACKET_INTERNAL_SECTION_SIZE); } - memcpy(_voxelPacketAt, buffer, bytes); - _voxelPacketAvailableBytes -= bytes; - _voxelPacketAt += bytes; - _voxelPacketWaiting = true; - - assert(_voxelPacketAvailableBytes >= 0); + if (bytes <= _voxelPacketAvailableBytes) { + memcpy(_voxelPacketAt, buffer, bytes); + _voxelPacketAvailableBytes -= bytes; + _voxelPacketAt += bytes; + _voxelPacketWaiting = true; + } } VoxelNodeData::~VoxelNodeData() { diff --git a/libraries/voxel-server-library/src/VoxelNodeData.h b/libraries/voxel-server-library/src/VoxelNodeData.h index fa0adc9e44..bd9e3eef16 100644 --- a/libraries/voxel-server-library/src/VoxelNodeData.h +++ b/libraries/voxel-server-library/src/VoxelNodeData.h @@ -27,7 +27,7 @@ public: VoxelNodeData(Node* owningNode); virtual ~VoxelNodeData(); - void resetVoxelPacket(); // resets voxel packet to after "V" header + void resetVoxelPacket(bool lastWasSurpressed = false); // resets voxel packet to after "V" header void writeToPacket(const unsigned char* buffer, int bytes); // writes to end of packet diff --git a/libraries/voxel-server-library/src/VoxelSendThread.cpp b/libraries/voxel-server-library/src/VoxelSendThread.cpp index 8c84b924c1..679f4ff524 100644 --- a/libraries/voxel-server-library/src/VoxelSendThread.cpp +++ b/libraries/voxel-server-library/src/VoxelSendThread.cpp @@ -105,9 +105,17 @@ int VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int& // obscure the packet and not send it. This allows the callers and upper level logic to not need to know about // this rate control savings. if (nodeData->shouldSuppressDuplicatePacket()) { - nodeData->resetVoxelPacket(); // we still need to reset it though! + nodeData->resetVoxelPacket(true); // we still need to reset it though! return packetsSent; // without sending... } + + const unsigned char* messageData = nodeData->getPacket(); + int numBytesPacketHeader = numBytesForPacketHeader(messageData); + const unsigned char* dataAt = messageData + numBytesPacketHeader; + dataAt += sizeof(VOXEL_PACKET_FLAGS); + VOXEL_PACKET_SEQUENCE sequence = (*(VOXEL_PACKET_SEQUENCE*)dataAt); + dataAt += sizeof(VOXEL_PACKET_SEQUENCE); + // If we've got a stats message ready to send, then see if we can piggyback them together if (nodeData->stats.isReadyToSend()) { @@ -127,12 +135,12 @@ int VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int& int thisWastedBytes = 0; _totalWastedBytes += thisWastedBytes; _totalBytes += nodeData->getPacketLength(); - _totalPackets++; + _totalPackets++; if (debug) { - qDebug("Adding stats to packet at %llu [%llu]: size:%d [%llu] wasted bytes:%d [%llu]\n", + qDebug("Adding stats to packet at %llu [%llu]: sequence: %d size:%d [%llu] wasted bytes:%d [%llu]\n", now, _totalPackets, - nodeData->getPacketLength(), _totalBytes, + sequence, nodeData->getPacketLength(), _totalBytes, thisWastedBytes, _totalWastedBytes); } @@ -147,13 +155,13 @@ int VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int& // there was nothing else to send. int thisWastedBytes = 0; _totalWastedBytes += thisWastedBytes; - _totalBytes += nodeData->getPacketLength(); + _totalBytes += statsMessageLength; _totalPackets++; if (debug) { qDebug("Sending separate stats packet at %llu [%llu]: size:%d [%llu] wasted bytes:%d [%llu]\n", now, _totalPackets, - nodeData->getPacketLength(), _totalBytes, + statsMessageLength, _totalBytes, thisWastedBytes, _totalWastedBytes); } @@ -171,10 +179,10 @@ int VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int& _totalBytes += nodeData->getPacketLength(); _totalPackets++; if (debug) { - qDebug("Sending packet at %llu [%llu]: size:%d [%llu] wasted bytes:%d [%llu]\n", + qDebug("Sending packet at %llu [%llu]: sequence: %d size:%d [%llu] wasted bytes:%d [%llu]\n", now, _totalPackets, - nodeData->getPacketLength(), _totalBytes, + sequence, nodeData->getPacketLength(), _totalBytes, thisWastedBytes, _totalWastedBytes); } } @@ -192,10 +200,10 @@ int VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int& _totalBytes += nodeData->getPacketLength(); _totalPackets++; if (debug) { - qDebug("Sending packet at %llu [%llu]: size:%d [%llu] wasted bytes:%d [%llu]\n", + qDebug("Sending packet at %llu [%llu]: sequence:%d size:%d [%llu] wasted bytes:%d [%llu]\n", now, _totalPackets, - nodeData->getPacketLength(), _totalBytes, + sequence, nodeData->getPacketLength(), _totalBytes, thisWastedBytes, _totalWastedBytes); } } diff --git a/libraries/voxels/src/VoxelSceneStats.cpp b/libraries/voxels/src/VoxelSceneStats.cpp index ebda4448b6..5bff303198 100644 --- a/libraries/voxels/src/VoxelSceneStats.cpp +++ b/libraries/voxels/src/VoxelSceneStats.cpp @@ -832,7 +832,8 @@ void VoxelSceneStats::trackIncomingVoxelPacket(unsigned char* messageData, ssize } // detect likely lost packets - if (sequence > (_incomingLastSequence+1)) { + VOXEL_PACKET_SEQUENCE expected = _incomingLastSequence+1; + if (sequence > expected) { _incomingLikelyLost++; }