properly handle sequence numbers to not skip when supressing duplicate packets

This commit is contained in:
ZappoMan 2013-11-27 15:33:48 -08:00
parent 7f9d0849bd
commit 040ad1853e
5 changed files with 37 additions and 23 deletions

View file

@ -48,6 +48,7 @@ void VoxelPacketProcessor::processPacket(sockaddr& senderAddress, unsigned char*
return; // bail since piggyback data doesn't match our versioning return; // bail since piggyback data doesn't match our versioning
} }
} else { } 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 return; // bail since no piggyback data
} }
} // fall through to piggyback message } // fall through to piggyback message

View file

@ -36,8 +36,7 @@ VoxelNodeData::VoxelNodeData(Node* owningNode) :
_lastVoxelPacketLength = 0; _lastVoxelPacketLength = 0;
_duplicatePacketCount = 0; _duplicatePacketCount = 0;
_sequenceNumber = 0; _sequenceNumber = 0;
resetVoxelPacket(true); // don't bump sequence
resetVoxelPacket();
} }
void VoxelNodeData::initializeVoxelSendThread(VoxelServer* voxelServer) { void VoxelNodeData::initializeVoxelSendThread(VoxelServer* voxelServer) {
@ -48,8 +47,11 @@ void VoxelNodeData::initializeVoxelSendThread(VoxelServer* voxelServer) {
} }
bool VoxelNodeData::packetIsDuplicate() const { 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()) { 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; return false;
} }
@ -88,7 +90,7 @@ bool VoxelNodeData::shouldSuppressDuplicatePacket() {
return shouldSuppress; 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 // 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 // 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 // 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; *sequenceAt = _sequenceNumber;
_voxelPacketAt += sizeof(VOXEL_PACKET_SEQUENCE); _voxelPacketAt += sizeof(VOXEL_PACKET_SEQUENCE);
_voxelPacketAvailableBytes -= sizeof(VOXEL_PACKET_SEQUENCE); _voxelPacketAvailableBytes -= sizeof(VOXEL_PACKET_SEQUENCE);
_sequenceNumber++; if (!(lastWasSurpressed || _lastVoxelPacketLength == VOXEL_PACKET_HEADER_SIZE)) {
_sequenceNumber++;
}
// pack in timestamp // pack in timestamp
VOXEL_PACKET_SENT_TIME now = usecTimestampNow(); 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); _voxelPacketAt += sizeof(VOXEL_PACKET_INTERNAL_SECTION_SIZE);
_voxelPacketAvailableBytes -= sizeof(VOXEL_PACKET_INTERNAL_SECTION_SIZE); _voxelPacketAvailableBytes -= sizeof(VOXEL_PACKET_INTERNAL_SECTION_SIZE);
} }
memcpy(_voxelPacketAt, buffer, bytes); if (bytes <= _voxelPacketAvailableBytes) {
_voxelPacketAvailableBytes -= bytes; memcpy(_voxelPacketAt, buffer, bytes);
_voxelPacketAt += bytes; _voxelPacketAvailableBytes -= bytes;
_voxelPacketWaiting = true; _voxelPacketAt += bytes;
_voxelPacketWaiting = true;
assert(_voxelPacketAvailableBytes >= 0); }
} }
VoxelNodeData::~VoxelNodeData() { VoxelNodeData::~VoxelNodeData() {

View file

@ -27,7 +27,7 @@ public:
VoxelNodeData(Node* owningNode); VoxelNodeData(Node* owningNode);
virtual ~VoxelNodeData(); 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 void writeToPacket(const unsigned char* buffer, int bytes); // writes to end of packet

View file

@ -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 // 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. // this rate control savings.
if (nodeData->shouldSuppressDuplicatePacket()) { 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... 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 we've got a stats message ready to send, then see if we can piggyback them together
if (nodeData->stats.isReadyToSend()) { if (nodeData->stats.isReadyToSend()) {
@ -127,12 +135,12 @@ int VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int&
int thisWastedBytes = 0; int thisWastedBytes = 0;
_totalWastedBytes += thisWastedBytes; _totalWastedBytes += thisWastedBytes;
_totalBytes += nodeData->getPacketLength(); _totalBytes += nodeData->getPacketLength();
_totalPackets++; _totalPackets++;
if (debug) { 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, now,
_totalPackets, _totalPackets,
nodeData->getPacketLength(), _totalBytes, sequence, nodeData->getPacketLength(), _totalBytes,
thisWastedBytes, _totalWastedBytes); thisWastedBytes, _totalWastedBytes);
} }
@ -147,13 +155,13 @@ int VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int&
// there was nothing else to send. // there was nothing else to send.
int thisWastedBytes = 0; int thisWastedBytes = 0;
_totalWastedBytes += thisWastedBytes; _totalWastedBytes += thisWastedBytes;
_totalBytes += nodeData->getPacketLength(); _totalBytes += statsMessageLength;
_totalPackets++; _totalPackets++;
if (debug) { if (debug) {
qDebug("Sending separate stats packet at %llu [%llu]: size:%d [%llu] wasted bytes:%d [%llu]\n", qDebug("Sending separate stats packet at %llu [%llu]: size:%d [%llu] wasted bytes:%d [%llu]\n",
now, now,
_totalPackets, _totalPackets,
nodeData->getPacketLength(), _totalBytes, statsMessageLength, _totalBytes,
thisWastedBytes, _totalWastedBytes); thisWastedBytes, _totalWastedBytes);
} }
@ -171,10 +179,10 @@ int VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int&
_totalBytes += nodeData->getPacketLength(); _totalBytes += nodeData->getPacketLength();
_totalPackets++; _totalPackets++;
if (debug) { 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, now,
_totalPackets, _totalPackets,
nodeData->getPacketLength(), _totalBytes, sequence, nodeData->getPacketLength(), _totalBytes,
thisWastedBytes, _totalWastedBytes); thisWastedBytes, _totalWastedBytes);
} }
} }
@ -192,10 +200,10 @@ int VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int&
_totalBytes += nodeData->getPacketLength(); _totalBytes += nodeData->getPacketLength();
_totalPackets++; _totalPackets++;
if (debug) { 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, now,
_totalPackets, _totalPackets,
nodeData->getPacketLength(), _totalBytes, sequence, nodeData->getPacketLength(), _totalBytes,
thisWastedBytes, _totalWastedBytes); thisWastedBytes, _totalWastedBytes);
} }
} }

View file

@ -832,7 +832,8 @@ void VoxelSceneStats::trackIncomingVoxelPacket(unsigned char* messageData, ssize
} }
// detect likely lost packets // detect likely lost packets
if (sequence > (_incomingLastSequence+1)) { VOXEL_PACKET_SEQUENCE expected = _incomingLastSequence+1;
if (sequence > expected) {
_incomingLikelyLost++; _incomingLikelyLost++;
} }