Files
MeshCore/src/helpers/TempRadioReplyBarrier.h
T
mikecarper a07f39c6dd Add per-profile TX routing and bridge filtering
Persist Companion TX preferences per contact and channel. Default repeater,
room, and sensor replies to both active TX profiles, with a reply-only force
option for an RX-only secondary profile. Track both reply copies before a
temporary-radio handoff and account for OTA copies under queue backpressure.

Add bridge/crossover filter modes and the third built-in wardriving filter,
plus compact filter CLI syntax, documentation, and CI coverage.

Fix quoted target names being interpreted as slot/key selectors, partial
recovery of invalid saved reply settings, filter suspension during tempradio2,
and unnecessary packet allocation while OTA traffic is throttled.

Validation: 1,477 native tests, 52 Python integration tests, 29 filter UI tests,
and five firmware builds covering ESP32, nRF52, and STM32 passed.
2026-09-15 01:58:43 -07:00

53 lines
1.8 KiB
C++

#pragma once
namespace mesh {
// A parameterized TempRadio command changes the modulation used to carry its
// own remote-CLI reply. A wall-clock delay cannot prove that the reply has
// left a busy outbound queue, so keep the scheduled handoff blocked by the
// exact packet objects on both profiles until Dispatcher reports TX completion.
// At least one successful TX permits the handoff, after both copies drain. This class is
// deliberately pointer-only: packet ownership stays with Dispatcher.
class TempRadioReplyBarrier {
const void* _packet = nullptr;
const void* _copy = nullptr;
bool _armed = false;
bool _succeeded = false;
bool remove(const void* packet) {
if (!_armed || packet == nullptr) return false;
if (packet == _packet) _packet = nullptr;
else if (packet == _copy) _copy = nullptr;
else return false;
return true;
}
public:
// Collect the Dispatcher-created second copy during queue admission. Retry
// bookkeeping can call onSendFail before admission; it must not resolve this.
void prepare(const void* packet) { clear(); _packet = packet; }
void trackCopy(const void* original, const void* copy) {
if (original && original == _packet && copy != original) _copy = copy;
}
void arm(const void* packet) {
if (packet != _packet) prepare(packet);
_armed = packet != nullptr;
}
void clear() { _packet = _copy = nullptr; _armed = _succeeded = false; }
bool waiting() const { return _armed && (_packet || _copy); }
bool complete(const void* packet) {
if (!remove(packet)) return false;
_succeeded = true;
return true;
}
// Cancel the transition only when every admitted copy has failed.
bool fail(const void* packet) {
return remove(packet) && !waiting() && !_succeeded;
}
};
} // namespace mesh