2022-12-06 14:08:04 +01:00
|
|
|
#pragma once
|
|
|
|
|
#include "ProtobufModule.h"
|
2025-07-25 06:23:45 +08:00
|
|
|
#include "concurrency/OSThread.h"
|
|
|
|
|
#include "graphics/Screen.h"
|
|
|
|
|
#include "graphics/SharedUIDisplay.h"
|
|
|
|
|
#include "input/InputBroker.h"
|
|
|
|
|
#if HAS_SCREEN
|
|
|
|
|
#include "OLEDDisplayUi.h"
|
|
|
|
|
#endif
|
2022-12-06 14:08:04 +01:00
|
|
|
|
2024-09-09 19:13:00 +02:00
|
|
|
#define ROUTE_SIZE sizeof(((meshtastic_RouteDiscovery *)0)->route) / sizeof(((meshtastic_RouteDiscovery *)0)->route[0])
|
|
|
|
|
|
2022-12-06 14:08:04 +01:00
|
|
|
/**
|
|
|
|
|
* A module that traces the route to a certain destination node
|
|
|
|
|
*/
|
2025-07-25 06:23:45 +08:00
|
|
|
enum TraceRouteRunState { TRACEROUTE_STATE_IDLE, TRACEROUTE_STATE_TRACKING, TRACEROUTE_STATE_RESULT, TRACEROUTE_STATE_COOLDOWN };
|
|
|
|
|
|
|
|
|
|
class TraceRouteModule : public ProtobufModule<meshtastic_RouteDiscovery>,
|
|
|
|
|
public Observable<const UIFrameEvent *>,
|
|
|
|
|
private concurrency::OSThread
|
2022-12-06 14:08:04 +01:00
|
|
|
{
|
2023-01-21 14:34:29 +01:00
|
|
|
public:
|
|
|
|
|
TraceRouteModule();
|
2022-12-06 14:08:04 +01:00
|
|
|
|
2025-07-25 06:23:45 +08:00
|
|
|
bool startTraceRoute(NodeNum node);
|
|
|
|
|
void launch(NodeNum node);
|
|
|
|
|
void handleTraceRouteResult(const String &result);
|
|
|
|
|
bool shouldDraw();
|
|
|
|
|
#if HAS_SCREEN
|
|
|
|
|
virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) override;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
const char *getNodeName(NodeNum node);
|
|
|
|
|
|
|
|
|
|
virtual bool wantUIFrame() override { return shouldDraw(); }
|
|
|
|
|
virtual Observable<const UIFrameEvent *> *getUIFrameObservable() override { return this; }
|
|
|
|
|
|
If a packet is heard multiple times, rebroadcast using the highest hop limit (#5534)
* If a packet is heard multiple times, rebroadcast using the highest hop limit
Sometimes a packet will be in the TX queue waiting to be transmitted,
when it is overheard being rebroadcast by another node, with a higher
hop limit remaining. When this occurs, modify the pending packet in
the TX queue to avoid unnecessarily wasting hops.
* Reprocess instead of modifying queued packet
In order to ensure that the traceroute module works correctly, rather
than modifying the hop limnit of the existing queued version of the
packet, simply drop it ifrom the queue and reprocess the version of the
packet with the superior hop limit.
* Update protobufs submodule
* Merge upstream/develop into overheard-hoptimisation branch
Resolved conflicts in:
- src/mesh/FloodingRouter.cpp: Integrated hop limit optimization with refactored duplicate handling
- src/mesh/MeshPacketQueue.h: Kept both hop_limit_lt parameter and new find() method
* Improve method naming and code clarity
- Rename findPacket() to getPacketFromQueue() for better clarity
- Make code DRY by having find() use getPacketFromQueue() internally
- Resolves method overloading conflict with clearer naming
* If a packet is heard multiple times, rebroadcast using the highest hop limit
Sometimes a packet will be in the TX queue waiting to be transmitted,
when it is overheard being rebroadcast by another node, with a higher
hop limit remaining. When this occurs, modify the pending packet in
the TX queue to avoid unnecessarily wasting hops.
* Improve router role checking using IS_ONE_OF macro
- Replace multiple individual role checks with cleaner IS_ONE_OF macro
- Add CLIENT_BASE support as suggested in PR #7992
- Include MeshTypes.h for IS_ONE_OF macro
- Makes code more maintainable and consistent with other parts of codebase
* Apply IS_ONE_OF improvement to NextHopRouter.cpp
- Replace multiple individual role checks with cleaner IS_ONE_OF macro
- Add CLIENT_BASE support for consistency
- Include MeshTypes.h for IS_ONE_OF macro
- Matches the pattern used in FloodingRouter.cpp
* Create and apply IS_ROUTER_ROLE() macro across codebase
- Add IS_ROUTER_ROLE() macro to meshUtils.h for consistent router role checking
- Update FloodingRouter.cpp to use macro in multiple locations
- Update NextHopRouter.cpp to use macro
- Include CLIENT_BASE role support
* Core Changes:
- Add hop_limit field to PacketRecord (17B→20B due to alignment)
- Extend wasSeenRecently() with wasUpgraded parameter
- Enable router optimization without duplicate app delivery
- Handle ROUTER_LATE delayed transmission properly
Technical Details:
- Memory overhead: ~4000 bytes for 1000 records
- Prevents duplicate message delivery while enabling routing optimization
- Maintains protocol integrity for ACK/NAK handling
- Supports upgrade from hop_limit=0 to hop_limit>0 scenarios
* Delete files accdentally added for merge
* Trunk formatting
* Packets are supposed to be unsigned. Thankfully, it's only a log message.
* Upgrade all packets, not just 0 hop packets.
* Not just unsigned, but hex. Updating packet log IDs.
* Fixed order of operations issue that prevented packetrs from being removed from the queue
* Fixing some bugs after testing. Only storing the maximum hop value in PacketRecord which makes sense. Also, updating messaging to make more sense in the logs.
* Fixed flow logic about how to handle re-inserting duplicate packets. Removed IS_ROUTER_ROLE macro and replaced it with better isRebroadcaster().
* Add logic to re-run modules, but avoid re-sending to phone.
* Refactor how to process the new packet with hops. Only update nodeDB and traceRouteModule.
* - Apply changes to both FloodingRouter and NextHopRouter classes to make packets mutable for traceroute
- MESHTASTIC_EXCLUDE_TRACEROUTE guard for when we don't want traceroute
* Allow MeshPacket to be modified in-place in processUpgradePacket
* let's not make a copy where a copy is unncessary.
---------
Co-authored-by: Clive Blackledge <clive@ansible.org>
Co-authored-by: Clive Blackledge <git@ansible.org>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-09-25 22:44:49 +12:00
|
|
|
void processUpgradedPacket(const meshtastic_MeshPacket &mp);
|
|
|
|
|
|
2023-01-21 14:34:29 +01:00
|
|
|
protected:
|
2023-01-21 18:22:19 +01:00
|
|
|
bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_RouteDiscovery *r) override;
|
2022-12-06 14:08:04 +01:00
|
|
|
|
2023-01-21 18:22:19 +01:00
|
|
|
virtual meshtastic_MeshPacket *allocReply() override;
|
2022-12-06 14:08:04 +01:00
|
|
|
|
2024-03-23 13:31:58 +01:00
|
|
|
/* Called before rebroadcasting a RouteDiscovery payload in order to update
|
2023-01-21 14:34:29 +01:00
|
|
|
the route array containing the IDs of nodes this packet went through */
|
2024-03-23 13:31:58 +01:00
|
|
|
void alterReceivedProtobuf(meshtastic_MeshPacket &p, meshtastic_RouteDiscovery *r) override;
|
2022-12-06 14:08:04 +01:00
|
|
|
|
2025-07-25 06:23:45 +08:00
|
|
|
virtual int32_t runOnce() override;
|
|
|
|
|
|
2023-01-21 14:34:29 +01:00
|
|
|
private:
|
2024-06-09 23:03:53 +02:00
|
|
|
// Call to add unknown hops (e.g. when a node couldn't decrypt it) to the route based on hopStart and current hopLimit
|
2024-08-18 00:34:32 +02:00
|
|
|
void insertUnknownHops(meshtastic_MeshPacket &p, meshtastic_RouteDiscovery *r, bool isTowardsDestination);
|
2024-06-09 23:03:53 +02:00
|
|
|
|
2023-01-21 14:34:29 +01:00
|
|
|
// Call to add your ID to the route array of a RouteDiscovery message
|
2024-08-18 00:34:32 +02:00
|
|
|
void appendMyIDandSNR(meshtastic_RouteDiscovery *r, float snr, bool isTowardsDestination, bool SNRonly);
|
2022-12-06 14:08:04 +01:00
|
|
|
|
2025-10-05 16:58:42 +02:00
|
|
|
// Update next-hops in the routing table based on the returned route
|
|
|
|
|
void updateNextHops(meshtastic_MeshPacket &p, meshtastic_RouteDiscovery *r);
|
|
|
|
|
|
|
|
|
|
// Helper to update next-hop for a single node
|
|
|
|
|
void maybeSetNextHop(NodeNum target, uint8_t nextHopByte);
|
|
|
|
|
|
2023-01-21 14:34:29 +01:00
|
|
|
/* Call to print the route array of a RouteDiscovery message.
|
|
|
|
|
Set origin to where the request came from.
|
|
|
|
|
Set dest to the ID of its destination, or NODENUM_BROADCAST if it has not yet arrived there. */
|
2024-08-18 00:34:32 +02:00
|
|
|
void printRoute(meshtastic_RouteDiscovery *r, uint32_t origin, uint32_t dest, bool isTowardsDestination);
|
2025-07-25 06:23:45 +08:00
|
|
|
|
|
|
|
|
TraceRouteRunState runState = TRACEROUTE_STATE_IDLE;
|
|
|
|
|
unsigned long lastTraceRouteTime = 0;
|
|
|
|
|
unsigned long resultShowTime = 0;
|
|
|
|
|
unsigned long cooldownMs = 30000;
|
|
|
|
|
unsigned long resultDisplayMs = 10000;
|
|
|
|
|
unsigned long trackingTimeoutMs = 10000;
|
|
|
|
|
String bannerText;
|
|
|
|
|
String resultText;
|
|
|
|
|
NodeNum tracingNode = 0;
|
|
|
|
|
bool initialized = false;
|
2022-12-06 14:08:04 +01:00
|
|
|
};
|
|
|
|
|
|
If a packet is heard multiple times, rebroadcast using the highest hop limit (#5534)
* If a packet is heard multiple times, rebroadcast using the highest hop limit
Sometimes a packet will be in the TX queue waiting to be transmitted,
when it is overheard being rebroadcast by another node, with a higher
hop limit remaining. When this occurs, modify the pending packet in
the TX queue to avoid unnecessarily wasting hops.
* Reprocess instead of modifying queued packet
In order to ensure that the traceroute module works correctly, rather
than modifying the hop limnit of the existing queued version of the
packet, simply drop it ifrom the queue and reprocess the version of the
packet with the superior hop limit.
* Update protobufs submodule
* Merge upstream/develop into overheard-hoptimisation branch
Resolved conflicts in:
- src/mesh/FloodingRouter.cpp: Integrated hop limit optimization with refactored duplicate handling
- src/mesh/MeshPacketQueue.h: Kept both hop_limit_lt parameter and new find() method
* Improve method naming and code clarity
- Rename findPacket() to getPacketFromQueue() for better clarity
- Make code DRY by having find() use getPacketFromQueue() internally
- Resolves method overloading conflict with clearer naming
* If a packet is heard multiple times, rebroadcast using the highest hop limit
Sometimes a packet will be in the TX queue waiting to be transmitted,
when it is overheard being rebroadcast by another node, with a higher
hop limit remaining. When this occurs, modify the pending packet in
the TX queue to avoid unnecessarily wasting hops.
* Improve router role checking using IS_ONE_OF macro
- Replace multiple individual role checks with cleaner IS_ONE_OF macro
- Add CLIENT_BASE support as suggested in PR #7992
- Include MeshTypes.h for IS_ONE_OF macro
- Makes code more maintainable and consistent with other parts of codebase
* Apply IS_ONE_OF improvement to NextHopRouter.cpp
- Replace multiple individual role checks with cleaner IS_ONE_OF macro
- Add CLIENT_BASE support for consistency
- Include MeshTypes.h for IS_ONE_OF macro
- Matches the pattern used in FloodingRouter.cpp
* Create and apply IS_ROUTER_ROLE() macro across codebase
- Add IS_ROUTER_ROLE() macro to meshUtils.h for consistent router role checking
- Update FloodingRouter.cpp to use macro in multiple locations
- Update NextHopRouter.cpp to use macro
- Include CLIENT_BASE role support
* Core Changes:
- Add hop_limit field to PacketRecord (17B→20B due to alignment)
- Extend wasSeenRecently() with wasUpgraded parameter
- Enable router optimization without duplicate app delivery
- Handle ROUTER_LATE delayed transmission properly
Technical Details:
- Memory overhead: ~4000 bytes for 1000 records
- Prevents duplicate message delivery while enabling routing optimization
- Maintains protocol integrity for ACK/NAK handling
- Supports upgrade from hop_limit=0 to hop_limit>0 scenarios
* Delete files accdentally added for merge
* Trunk formatting
* Packets are supposed to be unsigned. Thankfully, it's only a log message.
* Upgrade all packets, not just 0 hop packets.
* Not just unsigned, but hex. Updating packet log IDs.
* Fixed order of operations issue that prevented packetrs from being removed from the queue
* Fixing some bugs after testing. Only storing the maximum hop value in PacketRecord which makes sense. Also, updating messaging to make more sense in the logs.
* Fixed flow logic about how to handle re-inserting duplicate packets. Removed IS_ROUTER_ROLE macro and replaced it with better isRebroadcaster().
* Add logic to re-run modules, but avoid re-sending to phone.
* Refactor how to process the new packet with hops. Only update nodeDB and traceRouteModule.
* - Apply changes to both FloodingRouter and NextHopRouter classes to make packets mutable for traceroute
- MESHTASTIC_EXCLUDE_TRACEROUTE guard for when we don't want traceroute
* Allow MeshPacket to be modified in-place in processUpgradePacket
* let's not make a copy where a copy is unncessary.
---------
Co-authored-by: Clive Blackledge <clive@ansible.org>
Co-authored-by: Clive Blackledge <git@ansible.org>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-09-25 22:44:49 +12:00
|
|
|
extern TraceRouteModule *traceRouteModule;
|