mirror of
https://github.com/meshtastic/firmware.git
synced 2025-04-25 09:42:35 +00:00

Some checks are pending
CI / setup (check) (push) Waiting to run
CI / setup (esp32) (push) Waiting to run
CI / setup (esp32c3) (push) Waiting to run
CI / setup (esp32c6) (push) Waiting to run
CI / setup (esp32s3) (push) Waiting to run
CI / setup (nrf52840) (push) Waiting to run
CI / setup (rp2040) (push) Waiting to run
CI / setup (stm32) (push) Waiting to run
CI / check (push) Blocked by required conditions
CI / build-esp32 (push) Blocked by required conditions
CI / build-esp32-s3 (push) Blocked by required conditions
CI / build-esp32-c3 (push) Blocked by required conditions
CI / build-esp32-c6 (push) Blocked by required conditions
CI / build-nrf52 (push) Blocked by required conditions
CI / build-rpi2040 (push) Blocked by required conditions
CI / build-stm32 (push) Blocked by required conditions
CI / package-raspbian (push) Waiting to run
CI / package-raspbian-armv7l (push) Waiting to run
CI / package-native (push) Waiting to run
CI / build-docker (push) Waiting to run
CI / after-checks (push) Blocked by required conditions
CI / gather-artifacts (esp32) (push) Blocked by required conditions
CI / gather-artifacts (esp32c3) (push) Blocked by required conditions
CI / gather-artifacts (esp32c6) (push) Blocked by required conditions
CI / gather-artifacts (esp32s3) (push) Blocked by required conditions
CI / gather-artifacts (nrf52840) (push) Blocked by required conditions
CI / gather-artifacts (rp2040) (push) Blocked by required conditions
CI / gather-artifacts (stm32) (push) Blocked by required conditions
CI / release-artifacts (push) Blocked by required conditions
CI / release-firmware (esp32) (push) Blocked by required conditions
CI / release-firmware (esp32c3) (push) Blocked by required conditions
CI / release-firmware (esp32c6) (push) Blocked by required conditions
CI / release-firmware (esp32s3) (push) Blocked by required conditions
CI / release-firmware (nrf52840) (push) Blocked by required conditions
CI / release-firmware (rp2040) (push) Blocked by required conditions
CI / release-firmware (stm32) (push) Blocked by required conditions
Flawfinder Scan / Flawfinder (push) Waiting to run
Will always rebroadcast packets, but will do so after all other modes. Intended for router nodes that are there to provide additional coverage in areas not already covered by other routers, or to bridge around problematic terrain, but should not be given priority over other routers in order to avoid unnecessaraily consuming hops. By default, this role will rebroadcast during the normal client window. However, if another node is overheard rebroadcasting the packet, then it will be moved to a second window *after* the normal client one, with the same timing behaviour.
150 lines
5.0 KiB
C++
150 lines
5.0 KiB
C++
#include "MeshPacketQueue.h"
|
|
#include "NodeDB.h"
|
|
#include "configuration.h"
|
|
#include <assert.h>
|
|
|
|
#include <algorithm>
|
|
|
|
/// @return the priority of the specified packet
|
|
inline uint32_t getPriority(const meshtastic_MeshPacket *p)
|
|
{
|
|
auto pri = p->priority;
|
|
return pri;
|
|
}
|
|
|
|
/// @return "true" if "p1" is ordered before "p2"
|
|
bool CompareMeshPacketFunc(const meshtastic_MeshPacket *p1, const meshtastic_MeshPacket *p2)
|
|
{
|
|
assert(p1 && p2);
|
|
|
|
// If one packet is in the late transmit window, prefer the other one
|
|
if ((bool)p1->tx_after != (bool)p2->tx_after) {
|
|
return !p1->tx_after;
|
|
}
|
|
|
|
auto p1p = getPriority(p1), p2p = getPriority(p2);
|
|
// If priorities differ, use that
|
|
// for equal priorities, prefer packets already on mesh.
|
|
return (p1p != p2p) ? (p1p > p2p) : (!isFromUs(p1) && isFromUs(p2));
|
|
}
|
|
|
|
MeshPacketQueue::MeshPacketQueue(size_t _maxLen) : maxLen(_maxLen) {}
|
|
|
|
bool MeshPacketQueue::empty()
|
|
{
|
|
return queue.empty();
|
|
}
|
|
|
|
/**
|
|
* Some clients might not properly set priority, therefore we fix it here.
|
|
*/
|
|
void fixPriority(meshtastic_MeshPacket *p)
|
|
{
|
|
// We might receive acks from other nodes (and since generated remotely, they won't have priority assigned. Check for that
|
|
// and fix it
|
|
if (p->priority == meshtastic_MeshPacket_Priority_UNSET) {
|
|
// if a reliable message give a bit higher default priority
|
|
p->priority = (p->want_ack ? meshtastic_MeshPacket_Priority_RELIABLE : meshtastic_MeshPacket_Priority_DEFAULT);
|
|
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
|
// if acks/naks give very high priority
|
|
if (p->decoded.portnum == meshtastic_PortNum_ROUTING_APP) {
|
|
p->priority = meshtastic_MeshPacket_Priority_ACK;
|
|
// if text or admin, give high priority
|
|
} else if (p->decoded.portnum == meshtastic_PortNum_TEXT_MESSAGE_APP ||
|
|
p->decoded.portnum == meshtastic_PortNum_ADMIN_APP) {
|
|
p->priority = meshtastic_MeshPacket_Priority_HIGH;
|
|
// if it is a response, give higher priority to let it arrive early and stop the request being relayed
|
|
} else if (p->decoded.request_id != 0) {
|
|
p->priority = meshtastic_MeshPacket_Priority_RESPONSE;
|
|
// Also if we want a response, give a bit higher priority
|
|
} else if (p->decoded.want_response) {
|
|
p->priority = meshtastic_MeshPacket_Priority_RELIABLE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/** enqueue a packet, return false if full */
|
|
bool MeshPacketQueue::enqueue(meshtastic_MeshPacket *p)
|
|
{
|
|
// no space - try to replace a lower priority packet in the queue
|
|
if (queue.size() >= maxLen) {
|
|
return replaceLowerPriorityPacket(p);
|
|
}
|
|
|
|
// Find the correct position using upper_bound to maintain a stable order
|
|
auto it = std::upper_bound(queue.begin(), queue.end(), p, CompareMeshPacketFunc);
|
|
queue.insert(it, p); // Insert packet at the found position
|
|
return true;
|
|
}
|
|
|
|
meshtastic_MeshPacket *MeshPacketQueue::dequeue()
|
|
{
|
|
if (empty()) {
|
|
return NULL;
|
|
}
|
|
|
|
auto *p = queue.front();
|
|
queue.erase(queue.begin()); // Remove the highest-priority packet
|
|
return p;
|
|
}
|
|
|
|
meshtastic_MeshPacket *MeshPacketQueue::getFront()
|
|
{
|
|
if (empty()) {
|
|
return NULL;
|
|
}
|
|
|
|
auto *p = queue.front();
|
|
return p;
|
|
}
|
|
|
|
/** Attempt to find and remove a packet from this queue. Returns a pointer to the removed packet, or NULL if not found */
|
|
meshtastic_MeshPacket *MeshPacketQueue::remove(NodeNum from, PacketId id, bool tx_normal, bool tx_late)
|
|
{
|
|
for (auto it = queue.begin(); it != queue.end(); it++) {
|
|
auto p = (*it);
|
|
if (getFrom(p) == from && p->id == id && ((tx_normal && !p->tx_after) || (tx_late && p->tx_after))) {
|
|
queue.erase(it);
|
|
return p;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/** Attempt to find and remove a packet from this queue. Returns the packet which was removed from the queue */
|
|
bool MeshPacketQueue::replaceLowerPriorityPacket(meshtastic_MeshPacket *p)
|
|
{
|
|
|
|
if (queue.empty()) {
|
|
return false; // No packets to replace
|
|
}
|
|
|
|
// Check if the packet at the back has a lower priority than the new packet
|
|
auto &backPacket = queue.back();
|
|
if (!backPacket->tx_after && backPacket->priority < p->priority) {
|
|
// Remove the back packet
|
|
packetPool.release(backPacket);
|
|
queue.pop_back();
|
|
// Insert the new packet in the correct order
|
|
enqueue(p);
|
|
return true;
|
|
}
|
|
|
|
if (backPacket->tx_after) {
|
|
// Check if there's a non-late packet with lower priority
|
|
auto it = queue.end();
|
|
auto refPacket = *--it;
|
|
for (; refPacket->tx_after && it != queue.begin(); refPacket = *--it)
|
|
;
|
|
if (!refPacket->tx_after && refPacket->priority < p->priority) {
|
|
packetPool.release(refPacket);
|
|
enqueue(refPacket);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// If the back packet's priority is not lower, no replacement occurs
|
|
return false;
|
|
} |