This commit is contained in:
GUVWAF 2024-08-09 08:53:04 +02:00
parent e91dcb4ec3
commit 913268b132
2 changed files with 89 additions and 88 deletions

View File

@ -2,6 +2,51 @@
#include "FloodingRouter.h" #include "FloodingRouter.h"
/**
* An identifier for a globally unique message - a pair of the sending nodenum and the packet id assigned
* to that message
*/
struct GlobalPacketId {
NodeNum node;
PacketId id;
bool operator==(const GlobalPacketId &p) const { return node == p.node && id == p.id; }
explicit GlobalPacketId(const meshtastic_MeshPacket *p)
{
node = getFrom(p);
id = p->id;
}
GlobalPacketId(NodeNum _from, PacketId _id)
{
node = _from;
id = _id;
}
};
/**
* A packet queued for retransmission
*/
struct PendingPacket {
meshtastic_MeshPacket *packet;
/** The next time we should try to retransmit this packet */
uint32_t nextTxMsec = 0;
/** Starts at NUM_RETRANSMISSIONS -1(normally 3) and counts down. Once zero it will be removed from the list */
uint8_t numRetransmissions = 0;
PendingPacket() {}
explicit PendingPacket(meshtastic_MeshPacket *p);
};
class GlobalPacketIdHashFunction
{
public:
size_t operator()(const GlobalPacketId &p) const { return (std::hash<NodeNum>()(p.node)) ^ (std::hash<PacketId>()(p.id)); }
};
/* /*
Router which only relays if it is the next hop for a packet. Router which only relays if it is the next hop for a packet.
The next hop is set by the relay node of a packet, which bases this on information from either the NeighborInfoModule, or a The next hop is set by the relay node of a packet, which bases this on information from either the NeighborInfoModule, or a
@ -26,7 +71,23 @@ class NextHopRouter : public FloodingRouter
*/ */
virtual ErrorCode send(meshtastic_MeshPacket *p) override; virtual ErrorCode send(meshtastic_MeshPacket *p) override;
/** Do our retransmission handling */
virtual int32_t runOnce() override
{
// Note: We must doRetransmissions FIRST, because it might queue up work for the base class runOnce implementation
auto d = doRetransmissions();
int32_t r = FloodingRouter::runOnce();
return min(d, r);
}
protected: protected:
/**
* Pending retransmissions
*/
std::unordered_map<GlobalPacketId, PendingPacket, GlobalPacketIdHashFunction> pending;
/** /**
* Should this incoming filter be dropped? * Should this incoming filter be dropped?
* *
@ -42,10 +103,38 @@ class NextHopRouter : public FloodingRouter
constexpr static uint8_t NO_NEXT_HOP_PREFERENCE = 0; constexpr static uint8_t NO_NEXT_HOP_PREFERENCE = 0;
/**
* Try to find the pending packet record for this ID (or NULL if not found)
*/
PendingPacket *findPendingPacket(NodeNum from, PacketId id) { return findPendingPacket(GlobalPacketId(from, id)); }
PendingPacket *findPendingPacket(GlobalPacketId p);
/**
* Add p to the list of packets to retransmit occasionally. We will free it once we stop retransmitting.
*/
PendingPacket *startRetransmission(meshtastic_MeshPacket *p);
private: private:
/** /**
* Get the next hop for a destination, given the relay node * Get the next hop for a destination, given the relay node
* @return the node number of the next hop, 0 if no preference (fallback to FloodingRouter) * @return the node number of the next hop, 0 if no preference (fallback to FloodingRouter)
*/ */
uint8_t getNextHop(NodeNum to, uint8_t relay_node); uint8_t getNextHop(NodeNum to, uint8_t relay_node);
/**
* Stop any retransmissions we are doing of the specified node/packet ID pair
*
* @return true if we found and removed a transmission with this ID
*/
bool stopRetransmission(NodeNum from, PacketId id);
bool stopRetransmission(GlobalPacketId p);
/**
* Do any retransmissions that are scheduled (FIXME - for the time being called from loop)
*
* @return the number of msecs until our next retransmission or MAXINT if none scheduled
*/
int32_t doRetransmissions();
void setNextTx(PendingPacket *pending);
}; };

View File

@ -3,59 +3,11 @@
#include "NextHopRouter.h" #include "NextHopRouter.h"
#include <unordered_map> #include <unordered_map>
/**
* An identifier for a globalally unique message - a pair of the sending nodenum and the packet id assigned
* to that message
*/
struct GlobalPacketId {
NodeNum node;
PacketId id;
bool operator==(const GlobalPacketId &p) const { return node == p.node && id == p.id; }
explicit GlobalPacketId(const meshtastic_MeshPacket *p)
{
node = getFrom(p);
id = p->id;
}
GlobalPacketId(NodeNum _from, PacketId _id)
{
node = _from;
id = _id;
}
};
/**
* A packet queued for retransmission
*/
struct PendingPacket {
meshtastic_MeshPacket *packet;
/** The next time we should try to retransmit this packet */
uint32_t nextTxMsec = 0;
/** Starts at NUM_RETRANSMISSIONS -1(normally 3) and counts down. Once zero it will be removed from the list */
uint8_t numRetransmissions = 0;
PendingPacket() {}
explicit PendingPacket(meshtastic_MeshPacket *p);
};
class GlobalPacketIdHashFunction
{
public:
size_t operator()(const GlobalPacketId &p) const { return (std::hash<NodeNum>()(p.node)) ^ (std::hash<PacketId>()(p.id)); }
};
/** /**
* This is a mixin that extends Router with the ability to do (one hop only) reliable message sends. * This is a mixin that extends Router with the ability to do (one hop only) reliable message sends.
*/ */
class ReliableRouter : public NextHopRouter class ReliableRouter : public NextHopRouter
{ {
private:
std::unordered_map<GlobalPacketId, PendingPacket, GlobalPacketIdHashFunction> pending;
public: public:
/** /**
* Constructor * Constructor
@ -70,54 +22,14 @@ class ReliableRouter : public NextHopRouter
*/ */
virtual ErrorCode send(meshtastic_MeshPacket *p) override; virtual ErrorCode send(meshtastic_MeshPacket *p) override;
/** Do our retransmission handling */
virtual int32_t runOnce() override
{
// Note: We must doRetransmissions FIRST, because it might queue up work for the base class runOnce implementation
auto d = doRetransmissions();
int32_t r = FloodingRouter::runOnce();
return min(d, r);
}
protected: protected:
/** /**
* Look for acks/naks or someone retransmitting us * Look for acks/naks or someone retransmitting us
*/ */
virtual void sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Routing *c) override; virtual void sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Routing *c) override;
/**
* Try to find the pending packet record for this ID (or NULL if not found)
*/
PendingPacket *findPendingPacket(NodeNum from, PacketId id) { return findPendingPacket(GlobalPacketId(from, id)); }
PendingPacket *findPendingPacket(GlobalPacketId p);
/** /**
* We hook this method so we can see packets before FloodingRouter says they should be discarded * We hook this method so we can see packets before FloodingRouter says they should be discarded
*/ */
virtual bool shouldFilterReceived(const meshtastic_MeshPacket *p) override; virtual bool shouldFilterReceived(const meshtastic_MeshPacket *p) override;
/**
* Add p to the list of packets to retransmit occasionally. We will free it once we stop retransmitting.
*/
PendingPacket *startRetransmission(meshtastic_MeshPacket *p);
private:
/**
* Stop any retransmissions we are doing of the specified node/packet ID pair
*
* @return true if we found and removed a transmission with this ID
*/
bool stopRetransmission(NodeNum from, PacketId id);
bool stopRetransmission(GlobalPacketId p);
/**
* Do any retransmissions that are scheduled (FIXME - for the time being called from loop)
*
* @return the number of msecs until our next retransmission or MAXINT if none scheduled
*/
int32_t doRetransmissions();
void setNextTx(PendingPacket *pending);
}; };