mirror of
https://github.com/overte-org/overte.git
synced 2025-08-07 20:13:40 +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
|
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
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue