mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 09:24:00 +02:00
properly handle sequence numbers to not skip when supressing duplicate packets
This commit is contained in:
parent
7f9d0849bd
commit
040ad1853e
5 changed files with 37 additions and 23 deletions
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue