fix: gate module replies by request port (#11094)

This commit is contained in:
Ben Meadors
2026-07-21 10:19:38 +02:00
committed by GitHub
co-authored by GitHub
parent 7bdc2569e8
commit 0165e914a9
6 changed files with 411 additions and 44 deletions
+15 -4
View File
@@ -18,7 +18,7 @@ uint8_t MeshModule::numPeriodicModules = 0;
*/
meshtastic_MeshPacket *MeshModule::currentReply;
MeshModule::MeshModule(const char *_name) : name(_name)
MeshModule::MeshModule(const char *_name, meshtastic_PortNum _ourPortNum) : name(_name), ourPortNum(_ourPortNum)
{
// Can't trust static initializer order, so we check each time
if (!modules)
@@ -27,6 +27,12 @@ MeshModule::MeshModule(const char *_name) : name(_name)
modules->push_back(this);
}
bool MeshModule::replyPortMatches(meshtastic_PortNum modulePort, const meshtastic_MeshPacket &mp)
{
return modulePort != meshtastic_PortNum_UNKNOWN_APP && mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag &&
mp.decoded.portnum == modulePort;
}
void MeshModule::setup() {}
MeshModule::~MeshModule()
@@ -107,6 +113,7 @@ void MeshModule::callModules(meshtastic_MeshPacket &mp, RxSource src)
auto &pi = **i;
pi.currentRequest = ∓
pi.ignoreRequest = false;
/// We only call modules that are interested in the packet (and the message is destined to us or we are promiscious)
bool wantsPacket = (isDecoded || pi.encryptedOk) && (pi.isPromiscuous || toUs) && pi.wantPacket(&mp);
@@ -157,9 +164,13 @@ void MeshModule::callModules(meshtastic_MeshPacket &mp, RxSource src)
// better solution (FIXME) would be to let phones have their own distinct addresses and we 'route' to them like
// any other node.
if (isDecoded && mp.decoded.want_response && toUs && (!isFromUs(&mp) || isToUs(&mp)) && !currentReply) {
pi.sendResponse(mp);
if (replyPortMatches(pi.ourPortNum, mp)) {
pi.sendResponse(mp);
LOG_INFO("Asked module '%s' to send a response", pi.name);
} else {
LOG_DEBUG("Module '%s' cannot respond on portnum=%d", pi.name, mp.decoded.portnum);
}
ignoreRequest = ignoreRequest || pi.ignoreRequest; // If at least one module asks it, we may ignore a request
LOG_INFO("Asked module '%s' to send a response", pi.name);
} else {
LOG_DEBUG("Module '%s' considered", pi.name);
}
@@ -313,4 +324,4 @@ bool MeshModule::isRequestingFocus()
} else
return false;
}
#endif
#endif
+5 -2
View File
@@ -68,10 +68,12 @@ class MeshModule
/** Constructor
* name is for debugging output
*/
MeshModule(const char *_name);
MeshModule(const char *_name, meshtastic_PortNum _ourPortNum = meshtastic_PortNum_UNKNOWN_APP);
virtual ~MeshModule();
static bool replyPortMatches(meshtastic_PortNum modulePort, const meshtastic_MeshPacket &mp);
/** For use only by MeshService
*/
static void callModules(meshtastic_MeshPacket &mp, RxSource src = RX_SRC_RADIO);
@@ -88,6 +90,7 @@ class MeshModule
#endif
protected:
const char *name;
meshtastic_PortNum ourPortNum;
/** Most modules only care about packets that are destined for their node (i.e. broadcasts or has their node as the specific
recipient) But some plugs might want to 'sniff' packets that are merely being routed (passing through the current node). Those
@@ -103,7 +106,7 @@ class MeshModule
* flag */
bool encryptedOk = false;
/* We allow modules to ignore a request without sending an error if they have a specific reason for it. */
/* Per-packet flag cleared by callModules(); modules can suppress an error response for a specific request. */
bool ignoreRequest = false;
/**
+2 -5
View File
@@ -8,14 +8,11 @@
*/
class SinglePortModule : public MeshModule
{
protected:
meshtastic_PortNum ourPortNum;
public:
/** Constructor
* name is for debugging output
*/
SinglePortModule(const char *_name, meshtastic_PortNum _ourPortNum) : MeshModule(_name), ourPortNum(_ourPortNum) {}
SinglePortModule(const char *_name, meshtastic_PortNum _ourPortNum) : MeshModule(_name, _ourPortNum) {}
protected:
/**
@@ -38,4 +35,4 @@ class SinglePortModule : public MeshModule
return p;
}
};
};
+2 -14
View File
@@ -109,7 +109,7 @@ bool SerialModule::isValidConfig(const meshtastic_ModuleConfig_SerialConfig &con
return true;
}
SerialModuleRadio::SerialModuleRadio() : MeshModule("SerialModuleRadio")
SerialModuleRadio::SerialModuleRadio() : SinglePortModule("SerialModuleRadio", meshtastic_PortNum_SERIAL_APP)
{
switch (moduleConfig.serial.mode) {
case meshtastic_ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG:
@@ -330,18 +330,6 @@ void SerialModule::sendTelemetry(meshtastic_Telemetry m)
service->sendToMesh(p, RX_SRC_LOCAL, true);
}
/**
* Allocates a new mesh packet for use as a reply to a received packet.
*
* @return A pointer to the newly allocated mesh packet.
*/
meshtastic_MeshPacket *SerialModuleRadio::allocReply()
{
auto reply = allocDataPacket(); // Allocate a packet for sending
return reply;
}
/**
* Sends a payload to a specified destination node.
*
@@ -351,7 +339,7 @@ meshtastic_MeshPacket *SerialModuleRadio::allocReply()
void SerialModuleRadio::sendPayload(NodeNum dest, bool wantReplies)
{
const meshtastic_Channel *ch = (boundChannel != NULL) ? &channels.getByName(boundChannel) : NULL;
meshtastic_MeshPacket *p = allocReply();
meshtastic_MeshPacket *p = allocDataPacket();
if (!p)
return;
p->to = dest;
+2 -19
View File
@@ -40,7 +40,7 @@ extern SerialModule *serialModule;
* Radio interface for SerialModule
*
*/
class SerialModuleRadio : public MeshModule
class SerialModuleRadio : public SinglePortModule
{
uint32_t lastRxID = 0;
char outbuf[90] = "";
@@ -54,31 +54,14 @@ class SerialModuleRadio : public MeshModule
void sendPayload(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
protected:
virtual meshtastic_MeshPacket *allocReply() override;
/** Called to handle a particular incoming message
@return ProcessMessage::STOP if you've guaranteed you've handled this message and no other handlers should be considered for
it
*/
virtual ProcessMessage handleReceived(const meshtastic_MeshPacket &mp) override;
meshtastic_PortNum ourPortNum;
virtual bool wantPacket(const meshtastic_MeshPacket *p) override { return p->decoded.portnum == ourPortNum; }
meshtastic_MeshPacket *allocDataPacket()
{
// Update our local node info with our position (even if we don't decide to update anyone else)
meshtastic_MeshPacket *p = router->allocForSending();
if (!p)
return nullptr;
p->decoded.portnum = ourPortNum;
return p;
}
};
extern SerialModuleRadio *serialModuleRadio;
#endif
#endif