int OctreeInboundPacketProcessor::sendNackPackets() { int packetsSent = 0; if (_shuttingDown) { qDebug() << "OctreeInboundPacketProcessor::sendNackPackets() while shutting down... ignore"; return packetsSent; } char packet[MAX_PACKET_SIZE]; NodeToSenderStatsMapIterator i = _singleSenderStats.begin(); while (i != _singleSenderStats.end()) { QUuid nodeUUID = i.key(); SingleSenderStats nodeStats = i.value(); // check if this node is still alive. Remove its stats if it's dead. if (!isAlive(nodeUUID)) { i = _singleSenderStats.erase(i); continue; } // if there are packets from _node that are waiting to be processed, // don't send a NACK since the missing packets may be among those waiting packets. if (hasPacketsToProcessFrom(nodeUUID)) { i++; continue; } const SharedNodePointer& destinationNode = DependencyManager::get<NodeList>()->nodeWithUUID(nodeUUID); // retrieve sequence number stats of node, prune its missing set SequenceNumberStats& sequenceNumberStats = nodeStats.getIncomingEditSequenceNumberStats(); sequenceNumberStats.pruneMissingSet(); // construct nack packet(s) for this node const QSet<unsigned short int>& missingSequenceNumbers = sequenceNumberStats.getMissingSet(); int numSequenceNumbersAvailable = missingSequenceNumbers.size(); QSet<unsigned short int>::const_iterator missingSequenceNumberIterator = missingSequenceNumbers.constBegin(); while (numSequenceNumbersAvailable > 0) { char* dataAt = packet; int bytesRemaining = MAX_PACKET_SIZE; auto nodeList = DependencyManager::get<NodeList>(); // pack header int numBytesPacketHeader = nodeList->populatePacketHeader(packet, _myServer->getMyEditNackType()); dataAt += numBytesPacketHeader; bytesRemaining -= numBytesPacketHeader; // calculate and pack the number of sequence numbers to nack int numSequenceNumbersRoomFor = (bytesRemaining - sizeof(uint16_t)) / sizeof(unsigned short int); uint16_t numSequenceNumbers = std::min(numSequenceNumbersAvailable, numSequenceNumbersRoomFor); uint16_t* numSequenceNumbersAt = (uint16_t*)dataAt; *numSequenceNumbersAt = numSequenceNumbers; dataAt += sizeof(uint16_t); // pack sequence numbers to nack for (uint16_t i = 0; i < numSequenceNumbers; i++) { unsigned short int* sequenceNumberAt = (unsigned short int*)dataAt; *sequenceNumberAt = *missingSequenceNumberIterator; dataAt += sizeof(unsigned short int); missingSequenceNumberIterator++; } numSequenceNumbersAvailable -= numSequenceNumbers; // send it nodeList->writeUnverifiedDatagram(packet, dataAt - packet, destinationNode); packetsSent++; qDebug() << "NACK Sent back to editor/client... destinationNode=" << nodeUUID; } i++; } return packetsSent; }
int OctreeInboundPacketProcessor::sendNackPackets() { if (_shuttingDown) { qDebug() << "OctreeInboundPacketProcessor::sendNackPackets() while shutting down... ignore"; return 0; } auto nodeList = DependencyManager::get<NodeList>(); int packetsSent = 0; NodeToSenderStatsMapIterator i = _singleSenderStats.begin(); while (i != _singleSenderStats.end()) { QUuid nodeUUID = i.key(); SingleSenderStats nodeStats = i.value(); // check if this node is still alive. Remove its stats if it's dead. if (!isAlive(nodeUUID)) { i = _singleSenderStats.erase(i); continue; } // if there are packets from _node that are waiting to be processed, // don't send a NACK since the missing packets may be among those waiting packets. if (hasPacketsToProcessFrom(nodeUUID)) { ++i; continue; } const SharedNodePointer& destinationNode = DependencyManager::get<NodeList>()->nodeWithUUID(nodeUUID); // retrieve sequence number stats of node, prune its missing set SequenceNumberStats& sequenceNumberStats = nodeStats.getIncomingEditSequenceNumberStats(); sequenceNumberStats.pruneMissingSet(); // construct nack packet(s) for this node const QSet<unsigned short int>& missingSequenceNumbers = sequenceNumberStats.getMissingSet(); auto it = missingSequenceNumbers.constBegin(); if (it != missingSequenceNumbers.constEnd()) { auto nackPacketList = NLPacketList::create(_myServer->getMyEditNackType()); while (it != missingSequenceNumbers.constEnd()) { unsigned short int sequenceNumber = *it; nackPacketList->writePrimitive(sequenceNumber); ++it; } qDebug() << "NACK Sent back to editor/client... destinationNode=" << nodeUUID; packetsSent += nackPacketList->getNumPackets(); // send the list of nack packets nodeList->sendPacketList(std::move(nackPacketList), *destinationNode); } ++i; } return packetsSent; }