diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index b8ddbfa7..3c882d18 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -378,6 +378,12 @@ void MyMesh::queueMessage(const ContactInfo &from, uint8_t txt_type, mesh::Packe #endif } +bool MyMesh::filterRecvFloodPacket(mesh::Packet* packet) { + // REVISIT: try to determine which Region (from transport_codes[1]) that Sender is indicating for replies/responses + // if unknown, fallback to finding Region from transport_codes[0], the 'scope' used by Sender + return false; +} + void MyMesh::sendFloodScoped(const ContactInfo& recipient, mesh::Packet* pkt, uint32_t delay_millis) { // TODO: dynamic send_scope, depending on recipient and current 'home' Region if (send_scope.isNull()) { diff --git a/examples/companion_radio/MyMesh.h b/examples/companion_radio/MyMesh.h index bfb8bb18..fb0fb479 100644 --- a/examples/companion_radio/MyMesh.h +++ b/examples/companion_radio/MyMesh.h @@ -107,6 +107,7 @@ protected: int getInterferenceThreshold() const override; int calcRxDelay(float score, uint32_t air_time) const override; uint8_t getExtraAckTransmitCount() const override; + bool filterRecvFloodPacket(mesh::Packet* packet) override; void sendFloodScoped(const ContactInfo& recipient, mesh::Packet* pkt, uint32_t delay_millis=0) override; void sendFloodScoped(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t delay_millis=0) override; diff --git a/examples/simple_repeater/MyMesh.cpp b/examples/simple_repeater/MyMesh.cpp index 2cd81ef6..dce0f18b 100644 --- a/examples/simple_repeater/MyMesh.cpp +++ b/examples/simple_repeater/MyMesh.cpp @@ -404,21 +404,21 @@ uint32_t MyMesh::getDirectRetransmitDelay(const mesh::Packet *packet) { return getRNG()->nextInt(0, 5*t + 1); } -mesh::DispatcherAction MyMesh::onRecvPacket(mesh::Packet* pkt) { +bool MyMesh::filterRecvFloodPacket(mesh::Packet* pkt) { if (pkt->getRouteType() == ROUTE_TYPE_TRANSPORT_FLOOD) { - auto region = region_map.findMatch(pkt, REGION_ALLOW_FLOOD); + auto region = region_map.findMatch(pkt, REGION_DENY_FLOOD); if (region == NULL) { MESH_DEBUG_PRINTLN("onRecvPacket: unknown transport code for FLOOD packet"); - return ACTION_RELEASE; + return true; } } else if (pkt->getRouteType() == ROUTE_TYPE_FLOOD) { - if ((region_map.getWildcard().flags & REGION_ALLOW_FLOOD) == 0) { + if (region_map.getWildcard().flags & REGION_DENY_FLOOD) { MESH_DEBUG_PRINTLN("onRecvPacket: wildcard FLOOD packet not allowed"); - return ACTION_RELEASE; + return true; } } // otherwise do normal processing - return mesh::Mesh::onRecvPacket(pkt); + return false; } void MyMesh::onAnonDataRecv(mesh::Packet *packet, const uint8_t *secret, const mesh::Identity &sender, @@ -867,7 +867,7 @@ void MyMesh::handleCommand(uint32_t sender_timestamp, char *command, char *reply while (is_name_char(*ep)) ep++; if (*ep) { *ep++ = 0; } // set null terminator for end of name - while (*ep && *ep != 'F') ep++; // look for (optional flags) + while (*ep && *ep != 'F') ep++; // look for (optional) flags if (indent > 0 && indent < 8) { auto parent = load_stack[indent - 1]; @@ -875,7 +875,7 @@ void MyMesh::handleCommand(uint32_t sender_timestamp, char *command, char *reply auto old = region_map.findByName(np); auto nw = temp_map.putRegion(np, parent->id, old ? old->id : 0); // carry-over the current ID (if name already exists) if (nw) { - nw->flags = old ? old->flags : (*ep == 'F' ? REGION_ALLOW_FLOOD : 0); // carry-over flags from curr + nw->flags = old ? old->flags : (*ep == 'F' ? 0 : REGION_DENY_FLOOD); // carry-over flags from curr load_stack[indent] = nw; // keep pointers to parent regions, to resolve parent_id's } @@ -943,24 +943,26 @@ void MyMesh::handleCommand(uint32_t sender_timestamp, char *command, char *reply } else if (n >= 2 && strcmp(parts[1], "save") == 0) { bool success = region_map.save(_fs); strcpy(reply, success ? "OK" : "Err - save failed"); - } else if (n >= 3 && strcmp(parts[1], "allow") == 0) { - auto region = n >= 4 ? region_map.findByNamePrefix(parts[3]) : ®ion_map.getWildcard(); + } else if (n >= 2 && strcmp(parts[1], "allowf") == 0) { + auto region = n >= 3 ? region_map.findByNamePrefix(parts[2]) : ®ion_map.getWildcard(); if (region) { + region->flags &= ~REGION_DENY_FLOOD; + strcpy(reply, "OK"); + } else { + strcpy(reply, "Err - unknown region"); + } + } else if (n >= 2 && strcmp(parts[1], "denyf") == 0) { + auto region = n >= 3 ? region_map.findByNamePrefix(parts[2]) : ®ion_map.getWildcard(); + if (region) { + region->flags |= REGION_DENY_FLOOD; strcpy(reply, "OK"); - if (strcmp(parts[2], "F") == 0) { - region->flags = REGION_ALLOW_FLOOD; - } else if (strcmp(parts[2], "0") == 0) { - region->flags = 0; - } else { - sprintf(reply, "Err - invalid flag: %s", parts[2]); - } } else { strcpy(reply, "Err - unknown region"); } } else if (n >= 3 && strcmp(parts[1], "get") == 0) { auto region = region_map.findByNamePrefix(parts[2]); if (region) { - sprintf(reply, " %s %s", region->name, region->flags == REGION_ALLOW_FLOOD ? "F" : ""); + sprintf(reply, " %s %s", region->name, (region->flags & REGION_DENY_FLOOD) ? "" : "F"); } else { strcpy(reply, "Err - unknown region"); } diff --git a/examples/simple_repeater/MyMesh.h b/examples/simple_repeater/MyMesh.h index 9ab93747..83331541 100644 --- a/examples/simple_repeater/MyMesh.h +++ b/examples/simple_repeater/MyMesh.h @@ -149,7 +149,7 @@ protected: } #endif - mesh::DispatcherAction onRecvPacket(mesh::Packet* pkt) override; + bool filterRecvFloodPacket(mesh::Packet* pkt) override; void onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len) override; int searchPeersByHash(const uint8_t* hash) override; diff --git a/src/Mesh.cpp b/src/Mesh.cpp index 1ee6ce5c..71b8eaee 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -90,6 +90,8 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { return ACTION_RELEASE; // this node is NOT the next hop (OR this packet has already been forwarded), so discard. } + if (pkt->isRouteFlood() && filterRecvFloodPacket(pkt)) return ACTION_RELEASE; + DispatcherAction action = ACTION_RELEASE; switch (pkt->getPayloadType()) { diff --git a/src/Mesh.h b/src/Mesh.h index e96043e8..70fa80f3 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -43,6 +43,11 @@ protected: */ DispatcherAction routeRecvPacket(Packet* packet); + /** + * \returns true, if given packet should be NOT be processed. + */ + virtual bool filterRecvFloodPacket(Packet* packet) { return false; } + /** * \brief Check whether this packet should be forwarded (re-transmitted) or not. * Is sub-classes responsibility to make sure given packet is only transmitted ONCE (by this node) diff --git a/src/helpers/RegionMap.cpp b/src/helpers/RegionMap.cpp index 7b6456b4..074084ec 100644 --- a/src/helpers/RegionMap.cpp +++ b/src/helpers/RegionMap.cpp @@ -5,7 +5,7 @@ RegionMap::RegionMap(TransportKeyStore& store) : _store(&store) { next_id = 1; num_regions = 0; wildcard.id = wildcard.parent = 0; - wildcard.flags = REGION_ALLOW_FLOOD; // default behaviour, allow flood + wildcard.flags = 0; // default behaviour, allow flood and direct strcpy(wildcard.name, "(*)"); } @@ -100,7 +100,7 @@ RegionEntry* RegionMap::putRegion(const char* name, uint16_t parent_id, uint16_t if (id == 0 && num_regions >= MAX_REGION_ENTRIES) return NULL; // full! region = ®ions[num_regions++]; // alloc new RegionEntry - region->flags = 0; + region->flags = REGION_DENY_FLOOD; // DENY by default region->id = id == 0 ? next_id++ : id; StrHelper::strncpy(region->name, name, sizeof(region->name)); region->parent = parent_id; @@ -111,7 +111,7 @@ RegionEntry* RegionMap::putRegion(const char* name, uint16_t parent_id, uint16_t RegionEntry* RegionMap::findMatch(mesh::Packet* packet, uint8_t mask) { for (int i = 0; i < num_regions; i++) { auto region = ®ions[i]; - if ((region->flags & mask) == mask) { // does region allow this? (per 'mask' param) + if ((region->flags & mask) == 0) { // does region allow this? (per 'mask' param) TransportKey keys[4]; int num; if (region->name[0] == '#') { // auto hashtag region @@ -189,10 +189,10 @@ void RegionMap::printChildRegions(int indent, const RegionEntry* parent, Stream& out.print(' '); } - if (parent->flags & REGION_ALLOW_FLOOD) { - out.printf("%s F\n", parent->name); - } else { + if (parent->flags & REGION_DENY_FLOOD) { out.printf("%s\n", parent->name); + } else { + out.printf("%s F\n", parent->name); } for (int i = 0; i < num_regions; i++) { diff --git a/src/helpers/RegionMap.h b/src/helpers/RegionMap.h index 3858bfbd..5ad9df29 100644 --- a/src/helpers/RegionMap.h +++ b/src/helpers/RegionMap.h @@ -8,7 +8,8 @@ #define MAX_REGION_ENTRIES 32 #endif -#define REGION_ALLOW_FLOOD 0x01 +#define REGION_DENY_FLOOD 0x01 +#define REGION_DENY_DIRECT 0x02 // reserved for future struct RegionEntry { uint16_t id;