-
Notifications
You must be signed in to change notification settings - Fork 394
Pull-based Advertisement System #1374
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Pull-based Advertisement System #1374
Conversation
|
hundreds of users requesting node infos will flood even more |
First, there are no flood messages sent or received here (although you might have meant 'flood' differently here). Second, there is rate limiting on the repeater side ( |
|
@michielappelman First of all, thanks for your efforts! Especially the way you present and summarize your changes is simply amazing. I've rarely seen such a good description and also the design and testing looks very neat. I haven't looked at the code so far but I assume it looks just as nice. ;) Now to the actual idea: I think it could work. When I was reading the description I had the same hesitation as @marcelverdult expressed above, but on second thought: the user needs to know the full path to the repeater they want request an advert from (usually by receiving a message through it), so they can not use flood requests for "scraping". I think this hast the potential to limit the amount of traffic tremendously because people would either not care about repeater details or just request them once in a while. Using ratelimiting to enforce this sounds appropriate and reasonable to me. Additionally people interested in the mesh structure and performance can use the advert request as a simple form of traceroute/ping to see if they can reach a certain repeater. They don't need to run full traceroutes to see if the path works. |
|
every option you give people will ne abused. HA plugin can receive repater data? great all local repeater have free guest access so they add all of them. i can do bots? awesome lets spam the mesh! i‘d prefer a fixed system that makes the mesh work and ignore human „but i want to know“ |
|
@marcelverdult I see your point and I agree. The question is: can there be a compromise that is robust enough against abuse but still lets people gather information about the mesh and I think rate-limited, non-flood, requested adverts could be such a compromise. |
|
Marked this as draft because I missed a crucial limitation in testing: the Since all my radios are within range of each other all tests passed and I didn't notice this before... Need to re-think this a bit... When we do have the path built up, we could build a per-hop rate-limiter that looks at the pair of To be clear: we could fix this in a new firmware, but I want to make this compatible with intermediate repeaters that do not run this code (yet). |
|
Fixed the multi-hop response routing issue. The path is now embedded in the |
- Change GPS coordinates from double (8 bytes) to int32 (4 bytes) - Fix signature to sign pubkey+timestamp only (matches regular adverts) - Fix signature verification to verify pubkey+timestamp - Add tag to push notification for app matching - Update timeout notification to include tag Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Move CTL_TYPE_NODE_DISCOVER_REQ/RESP defines to Packet.h - Change CTL_TYPE_ADVERT_REQUEST/RESPONSE to 0xA0/0xA1 to avoid conflict with node discovery response (0x90-0x9F range) - Remove duplicate defines from repeater and sensor examples Co-Authored-By: Claude Opus 4.5 <[email protected]>
Replace array of PendingAdvertRequest structs with simple variables: - pending_advert_request (tag, 0 = none) - pending_advert_request_time (millis when created) This aligns with how other pending requests (login, status, etc.) work. Only one advert request can be pending at a time now. Co-Authored-By: Claude Opus 4.5 <[email protected]>
The app handles its own timeouts - no need for the companion radio to track them. Co-Authored-By: Claude Opus 4.5 <[email protected]>
The int32 values are sent directly to the app, no conversion needed. Co-Authored-By: Claude Opus 4.5 <[email protected]>
payloads.md: - Add ADVERT_REQUEST (0xA0) control sub-type - Add ADVERT_RESPONSE (0xA1) control sub-type with all fields and flags protocol_guide.md: - Add CMD_REQUEST_ADVERT (0x39) command - Add PUSH_CODE_ADVERT_RESPONSE (0x8F) to packet types - Add parsing pseudocode for advert response - Update response matching table Co-Authored-By: Claude Opus 4.5 <[email protected]>
Change ADVERT_RESPONSE from 0xA1 to 0xB0 so each control subtype has a unique upper nibble per the protocol convention. Update handlers to use nibble matching consistently. Co-Authored-By: Claude Opus 4.5 <[email protected]>
This reduces unnecessary network traffic since repeater adverts are primarily useful for local neighbor discovery (zero-hop), not for multi-hop propagation. Co-Authored-By: Claude Opus 4.5 <[email protected]>
Restructured packet to match regular advert pattern: - Signature now covers pubkey + timestamp + app_data - app_data includes: adv_type, node_name, flags, and all optional fields - This prevents intermediate nodes from tampering with any metadata Co-Authored-By: Claude Opus 4.5 <[email protected]>
5f151ef to
c8073e2
Compare
DIRECT routing consumes the header path at each hop, so the target node couldn't reverse it for the response. This fix: - Embeds the forward path in the ADVERT_REQUEST payload - Target extracts path, excludes itself (last element), and reverses - For direct neighbors (path=[target]), response sent as zero-hop - Works with stock firmware intermediate nodes (they only use header) Example: path [0x23, 0x1F] → response path [0x23] Co-Authored-By: Claude Opus 4.5 <[email protected]>
c8073e2 to
dc9b66f
Compare
Problem
Repeater flood advertisements are a significant source of airtime consumption in MeshCore networks. Each repeater periodically broadcasts its identity across the entire mesh, which:
Related discussions and PRs attempting to address repeater airtime:
flood_advert_intervaldefaults: Set default of flood_advert_interval to 48h, minimum interval to 12h #1217Solution
This PR implements a pull-based (on-demand) advertisement system that allows clients to request advertisement data from specific nodes when needed, rather than relying solely on periodic broadcasts.
Key Benefits
Behavior Changes for Repeaters
This PR makes two significant changes to repeater behavior:
1. Flood Adverts Disabled
Repeaters no longer send automatic flood advertisements. The
flood_advert_intervalis now disabled by default for new installs. Repeaters will:2. Incoming Flood Adverts from Repeaters Dropped
When a repeater receives a flood advert from another repeater, it is dropped and not forwarded. This prevents the "flood advert cascade" that consumes significant airtime in larger networks.
Flood adverts from companions, room servers, and sensors are still forwarded normally.
3. GPS Location Removed from Zero-Hop Adverts
Zero-hop advertisements no longer include GPS coordinates, regardless of the
advert.loc.policysetting. This provides:GPS coordinates are now only shared via pull-advert responses when a client explicitly requests extended metadata.
Important
Zero-Hop Adverts must stay enabled
Repeaters still need zero-hop advertisements for direct neighbors to discover them. The default
advert.intervalis 60 minutes for new installs.If you previously set
advert.intervalto 0 to reduce airtime, you must re-enable it:Without zero-hop adverts, direct neighbors won't know the repeater exists and won't be able to send pull-advert requests to it.
Summary of Advert Behavior
How It Works
Multi-Hop Request (via intermediate node)
sequenceDiagram participant App as Companion App participant Companion as Companion Radio participant Stock as Intermediate Repeater<br/>(stock firmware) participant Target as Target Repeater<br/>(new firmware) App->>Companion: CMD_REQUEST_ADVERT (0x3A)<br/>prefix=0x1F, path=[0x23, 0x1F] activate Companion Companion->>Stock: [RF] ADVERT_REQUEST (0x20)<br/>path=[0x23, 0x1F] Note over Stock: Forwards packet normally<br/>(no code changes needed) Stock->>Target: [RF] ADVERT_REQUEST (0x20)<br/>path=[0x1F] activate Target Note over Target: Builds signed response<br/>with extended metadata Target->>Stock: [RF] ADVERT_RESPONSE (0x30)<br/>signed payload deactivate Target Stock->>Companion: [RF] ADVERT_RESPONSE (0x30) Note over Companion: Verifies signature,<br/>strips it, forwards to app Companion->>App: PUSH_ADVERT_RESPONSE (0x8F) deactivate CompanionRequest Flow Summary
CMD_REQUEST_ADVERT(0x3A) to companion with target prefix and pathCTL_TYPE_ADVERT_REQUEST(0x20) over RF using DIRECT routingPUSH_CODE_ADVERT_RESPONSE(0x8F)Response Contents
Total: 139-179 bytes depending on optional fields (fits within MAX_PACKET_PAYLOAD of 184 bytes)
Backward Compatibility
This implementation is fully backward compatible:
Why it works: The control packet sub-types use values without the high bit set (0x20/0x30 instead of 0xA0/0xB0). In
Mesh.cpp, only sub-types with(payload[0] & 0x80) != 0are restricted to zero-hop. This allows pull-advert packets to traverse multiple hops through stock firmware nodes.Testing
Hardware Test Environment
companion_radio_usbsimple_repeaterAll tests performed over real RF links, not simulated.
Summary of changes
Core (
src/)CTL_TYPE_ADVERT_REQUEST(0x20) andCTL_TYPE_ADVERT_RESPONSE(0x30)PAYLOAD_TYPE_CONTROLhandling for multi-hop deliveryRepeater (
examples/simple_repeater/)handleAdvertRequest()to process requests and build signed responsesCompanion (
examples/companion_radio/)CMD_REQUEST_ADVERT(0x3A) command handler andhandleAdvertResponse()pending_advert_requestfieldCLI (
src/helpers/)node_desc[32]field toNodePrefsset node.desc/get node.desccommandsPython Client Support
The meshcore_py Python client has been updated with full support for pull-based adverts:
request_advert(prefix, path)commandADVERT_RESPONSEevent type and parserPR link: meshcore-dev/meshcore_py#45
Usage Example