mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-10-15 21:20:03 +00:00
upstream dev sync + bump to 1.18
This commit is contained in:
@@ -233,7 +233,7 @@ Path_len byte:
|
||||
|
||||
**Flood routing**: Packet has no destination path. Each relay node appends its identity hash to `path[]` and retransmits. Priority decreases with hop count. `allowPacketForward()` is the gatekeeper.
|
||||
|
||||
**Direct routing**: Packet carries a source-routed `path[]`. Each relay node checks if the first path hash matches its own identity, removes itself, and forwards. Path is built from previous flood packets' accumulated hashes.
|
||||
**Direct routing**: Packet carries a source-routed `path[]`. Each relay node checks if the first path hash matches its own identity, removes itself, and forwards. Path is built from previous flood packets' accumulated hashes. Every forwarded direct packet, ACKs included (upstream 1.18.0), waits `getDirectRetransmitDelay()`; extra multi-ACKs and the final ACK are 300 ms apart.
|
||||
|
||||
**Deduplication**: `SimpleMeshTables` maintains a circular buffer of 160 packet hashes (8 bytes each, SHA-256 truncated); ACKs are deduped through the same packet-hash path. `wasSeen()` is a pure query; call sites insert explicitly via `markSeen()` to prevent duplicate processing and retransmission.
|
||||
|
||||
@@ -727,7 +727,7 @@ default) is migrated to 3200 once (`zc.aoff_set`).
|
||||
Autonomous operation features:
|
||||
- **Authentication**: Password-based login with timestamp replay protection (120s window)
|
||||
- **Permission levels**: GUEST(0), READ_ONLY(1), READ_WRITE(2), ADMIN(3)
|
||||
- **Region filtering**: `RegionMap` with transport key matching per flood packet
|
||||
- **Region filtering**: `RegionMap` with transport key matching per flood packet. Un-scoped floods (`mesh::isUnscopedFlood()`: plain floods, and transport floods with code 0 as upstream 1.18.0) go to the wildcard `*`, whose deny-flood flag and `flood.max.unscoped` apply to both; upstream exempts the code-0 case from both (LLD 02 section 16)
|
||||
- **Rate limiting**: 4 requests per 120s (discovery), 4 per 180s (anonymous), 4 failed logins per 180s
|
||||
- **Node discovery**: answers discovery requests only while forwarding is on. With `advert.interval` and `flood.advert.interval` both `0` the node is hidden and does not answer, as upstream (`isHiddenNode()`); the request still counts against the discovery rate limit
|
||||
- **Neighbor tracking**: RSSI/SNR/name/timestamp table (`CONFIG_ZEPHCORE_MAX_NEIGHBOURS`, default 50 slots)
|
||||
|
||||
@@ -102,6 +102,7 @@ Every clock set (these commands, GPS, the app, mesh time sync, SNTP) is also wri
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `room.post <message>` | Post a message to the shared room as the server itself (system post). Pushed to clients like any other post. |
|
||||
| `set repeat on` | Replies `ERR - repeat now deprecated`, as upstream (1.18.0): a room server never forwards other nodes' packets. `set repeat off` and `get repeat` are the common commands |
|
||||
|
||||
---
|
||||
|
||||
@@ -125,6 +126,8 @@ Regions control which flood packets the repeater forwards. The region tree is hi
|
||||
| `region list allowed` | List all regions that allow floods |
|
||||
| `region list denied` | List all regions that deny floods |
|
||||
|
||||
**Un-scoped floods:** plain floods, and transport floods whose first code is `0` (no region computes `0`; as upstream 1.18.0). The wildcard `*` decides them: `region denyf *` stops forwarding them, and `flood.max.unscoped` limits their hops. Upstream applies neither to the code-`0` case; ZephCore applies both. A reply to such a request is sent un-scoped.
|
||||
|
||||
**Region load format:** one region per line, indented with spaces to indicate depth. Append `F` after the name to mark flood-allowed (otherwise flood is denied by default).
|
||||
|
||||
**`region def` format:** space-separated tokens; a cursor starts at `*`. Each token is `name` (create child of cursor, advance cursor to it) or `name|jump` / `name,jump` (create child of cursor, then move cursor to the existing region `jump`). Does **not** auto-save — follow with `region save`. Reply is the updated region tree. Example — branched tree: `region def west pnw or pdx|pnw wa sw-wa`. Example — flat list: `region def west|* pnw|* or|* pdx|*`.
|
||||
@@ -434,7 +437,7 @@ four radio parameters together, since they are one interop-critical set.
|
||||
| `set direct.txdelay <value>` | | Accepted for prefs compatibility — **ignored** (direct.txdelay is adaptive) |
|
||||
| `set backoff.multiplier <m>` | 0.0–2.0 | *(ZephCore only)* Per-dupe reactive backoff multiplier (0 = disable reactive backoff) |
|
||||
| `set flood.max <count>` | 0–64 | Maximum flood retransmit hops |
|
||||
| `set flood.max.unscoped <count>` | 0–64 | Hop limit for un-scoped floods only (default 64 = same as flood.max); scoped/transport floods still use flood.max |
|
||||
| `set flood.max.unscoped <count>` | 0–64 | Hop limit for un-scoped floods only, including transport floods with code `0` (default 64 = same as flood.max); scoped/transport floods still use flood.max |
|
||||
| `set flood.max.advert <count>` | 0–64 | Hop limit for ADVERT floods only (default 8); curbs advert churn independent of flood.max |
|
||||
| `set flood.advert.interval <hours>` | `0` (off) or 3–168 | How often the repeater floods its own advertisement. `0` disables periodic flood adverts. With `advert.interval` also `0` the repeater is hidden: it stops answering node discovery requests (`discover.neighbors`, the app's discover) as well. |
|
||||
| `set advert.interval <mins>` | `0` (off) or min–240 | How often the repeater sends local (zero-hop) advertisements. `0` — the default — disables them. Stored halved (the pref holds minutes/2), so odd values round down. |
|
||||
|
||||
+1
-1
@@ -46,4 +46,4 @@ On a 2.4 GHz preset there is no off-grid frequency, and the display and the CLI
|
||||
|
||||
Up to 1.17.7 the display toggle turned forwarding on without changing the frequency, so a companion
|
||||
could end up repeating on the live mesh. A node left in that state stops forwarding when it boots
|
||||
1.17.8 or later, and shows off-grid mode as off.
|
||||
1.18.0 or later, and shows off-grid mode as off.
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
# ZephCore 1.17.8-zephcore
|
||||
|
||||
Off-grid mode from the display no longer turns a companion into a repeater on the live mesh. Button
|
||||
fixes on four boards with a display: the Station G2's button now drives the pages, and
|
||||
Power Off, DFU and Offgrid can be confirmed on the Heltec Mesh Node T1 and both LR2021 LoRa Plus EVK
|
||||
kits.
|
||||
|
||||
> [!NOTE]
|
||||
> A normal upgrade keeps your identity, settings, contacts and phone pairing.
|
||||
|
||||
---
|
||||
|
||||
## Off-grid mode: only on the off-grid frequencies
|
||||
|
||||
Off-grid mode makes a companion forward packets for others, for a group of handhelds out of reach of
|
||||
any repeater. It belongs on three frequencies set aside for it: 433.000, 869.495 and 918.000 MHz. The
|
||||
app only allows it there, but the Offgrid toggle on the display switched forwarding on without
|
||||
changing the frequency, so the node repeated everything it heard on the live mesh.
|
||||
|
||||
- **The display toggle now moves the node.** Turning Offgrid on goes to the off-grid frequency nearest
|
||||
to the one you are on and starts forwarding; turning it off returns to the frequency you came from.
|
||||
Bandwidth, spreading factor, coding rate and TX power stay as they are.
|
||||
- **A companion never forwards on any other frequency.** If you had switched Offgrid on from the
|
||||
display on an earlier version, the node stops repeating after this update and shows Offgrid as off.
|
||||
Nothing else changes; turn it on again if you want off-grid mode.
|
||||
- **`set repeat on` / `set repeat off` work on a companion** and do the same as the display toggle;
|
||||
`get repeat` shows the real state. Before, they answered but did nothing.
|
||||
- **The display follows the app.** Offgrid switched from the app or the CLI now shows on the display
|
||||
page within a few seconds.
|
||||
|
||||
While off-grid mode is on, the node is off your normal mesh. How it works: [OFFGRID.md](../docs/OFFGRID.md).
|
||||
|
||||
Thanks to N8HOP for the report.
|
||||
|
||||
## Station G2: the user button drives the display
|
||||
|
||||
Until now a press of the user button only woke the display: the pages could not be turned, and
|
||||
nothing on them could be run. The button now works as on the other one-button boards:
|
||||
|
||||
- **one press**: next page,
|
||||
- **two presses**: previous page,
|
||||
- **hold for one second**: run the item on the page (Bluetooth on/off, send an advert, GPS on/off,
|
||||
and so on).
|
||||
|
||||
Offgrid, DFU and Power Off ask for confirmation: hold the button again within 3 seconds.
|
||||
|
||||
Reports of how it behaves on your Station G2 are welcome.
|
||||
|
||||
## Heltec Mesh Node T1 and LR2021 LoRa Plus EVK: Power Off, DFU and Offgrid can be confirmed
|
||||
|
||||
On these boards Power Off, DFU and Offgrid could not be confirmed from the display. The confirmation
|
||||
is a second long press of the user button, and it was accepted only within half a second of the
|
||||
first, which a long press cannot meet: every long press asked for the confirmation again. It now has
|
||||
3 seconds, as on the other one-button boards.
|
||||
|
||||
The confirmation is a second **hold**. A short press pages on instead, which on the Power Off page
|
||||
goes back to the first page.
|
||||
|
||||
## GPS: a fix could set the clock to an old time
|
||||
|
||||
On a repeater with a GPS, a fix could set the clock hours back. The next fix usually put it right
|
||||
again, but until then the node's adverts and replies carried the old time, and mesh time sync was not
|
||||
allowed to correct it.
|
||||
|
||||
Right after waking, a GPS receiver can report an estimated position for a few seconds: its last
|
||||
position and its own clock, before any satellite has confirmed them. These were accepted as a fix.
|
||||
If the receiver's clock had not kept time while it slept, that old time was written to the node.
|
||||
|
||||
- **Only positions solved from satellites count as a fix**, and five in a row are needed (was three).
|
||||
A fix takes about two seconds longer.
|
||||
- This applies to every board with a GPS.
|
||||
|
||||
It was reported on a SenseCAP Solar P1 with `set gps standby` raised to 48 hours, which keeps the
|
||||
receiver powered while it sleeps. With the default (one hour) a repeater switches the receiver off
|
||||
between its 48-hour fixes.
|
||||
|
||||
Good to know: a telemetry request from a logged-in client (anything above guest) wakes a repeater's
|
||||
GPS for a fresh fix, so the GPS can run more often than the `gps duty` interval.
|
||||
|
||||
Thanks to **Innocent Killer 101** for the report and the measurements.
|
||||
@@ -0,0 +1,50 @@
|
||||
# ZephCore 1.18.0-zephcore
|
||||
|
||||
Safer off-grid mode, working buttons on four boards with a display, a GPS clock fix, and the
|
||||
changes from upstream MeshCore 1.18.0.
|
||||
|
||||
> [!NOTE]
|
||||
> A normal upgrade keeps your identity, settings, contacts and phone pairing.
|
||||
|
||||
---
|
||||
|
||||
## Off-grid mode stays off the live mesh
|
||||
|
||||
Off-grid mode makes a companion forward packets for nearby handhelds when no repeater is in reach. It
|
||||
belongs on 433.000, 869.495 or 918.000 MHz, but the display's Offgrid toggle turned forwarding on
|
||||
without changing the frequency, so the node repeated everything on your normal mesh.
|
||||
|
||||
- **Turning Offgrid on now moves the node** to the nearest off-grid frequency; turning it off returns
|
||||
to the frequency you came from. Bandwidth, SF, CR and TX power are kept.
|
||||
- **A companion never forwards anywhere else.** If you enabled Offgrid from the display before, it
|
||||
shows as off after the update; turn it on again if you want it.
|
||||
- **`set repeat on|off` works on a companion** and does the same as the toggle. The display also
|
||||
follows changes made from the app.
|
||||
|
||||
More in [OFFGRID.md](../docs/OFFGRID.md). Thanks to **N8HOP** for the report.
|
||||
|
||||
## Buttons
|
||||
|
||||
- **Station G2:** the user button now works like on other one-button boards: one press for the next
|
||||
page, two for the previous page, hold for a second to run the item.
|
||||
- **Heltec Mesh Node T1, both LR2021 LoRa Plus EVK kits:** Power Off, DFU and Offgrid can be
|
||||
confirmed again.
|
||||
- On all four boards the confirmation is a second **hold** within 3 seconds.
|
||||
|
||||
## GPS no longer sets the clock to an old time
|
||||
|
||||
Just after waking, a GPS receiver can report its last position and its own, possibly stale, clock
|
||||
before any satellite confirms them. That was taken as a fix and could set a repeater's clock hours
|
||||
back. Now only satellite-solved positions count, five in a row. A fix takes about two seconds longer.
|
||||
This applies to every board with a GPS. Thanks to **Innocent Killer 101** for the report and the
|
||||
measurements.
|
||||
|
||||
## From upstream MeshCore 1.18.0
|
||||
|
||||
- **Acknowledgements on direct routes are relayed after a short random delay**, like other direct
|
||||
packets, and with `multi.acks 1` the two copies go out 300 ms apart. This means fewer lost
|
||||
acknowledgements.
|
||||
- **Floods with transport code 0 are treated as un-scoped.** Unlike upstream, ZephCore applies your
|
||||
`flood.max.unscoped` and `region denyf *` settings to them.
|
||||
- **Room server:** `set repeat on` now answers `ERR - repeat now deprecated`. A room server never
|
||||
forwarded packets anyway.
|
||||
@@ -352,6 +352,11 @@
|
||||
"name": "Scoped unscoped and advert hop boundaries",
|
||||
"source": "tests/unit/policy_tests.cpp"
|
||||
},
|
||||
{
|
||||
"id": "UNIT-POLICY-003",
|
||||
"name": "Transport flood with code 0 is un-scoped, other codes and routes are not",
|
||||
"source": "tests/unit/policy_tests.cpp"
|
||||
},
|
||||
{
|
||||
"id": "UNIT-OFFGRID-001",
|
||||
"name": "Off-grid frequency: the three allowed, nearest per band, none above sub-GHz",
|
||||
|
||||
@@ -18,6 +18,7 @@ TEST(reply_routes, "UNIT-POLICY-001", "Reply routing and scope truth tables") {
|
||||
}
|
||||
TEST(hop_limits, "UNIT-POLICY-002", "Scoped unscoped and advert hop boundaries") {
|
||||
Packet p;
|
||||
p.transport_codes[0] = 0x1234; p.transport_codes[1] = 0;
|
||||
for (uint8_t route : {ROUTE_TYPE_FLOOD, ROUTE_TYPE_TRANSPORT_FLOOD}) {
|
||||
for (uint8_t type : {PAYLOAD_TYPE_ADVERT, PAYLOAD_TYPE_TXT_MSG}) {
|
||||
p.header = route | (type << 2);
|
||||
@@ -31,6 +32,25 @@ TEST(hop_limits, "UNIT-POLICY-002", "Scoped unscoped and advert hop boundaries")
|
||||
p.header = ROUTE_TYPE_FLOOD; p.path_len = 0;
|
||||
CHECK(isFloodHopLimitExceeded(&p, 5, 0, 2));
|
||||
}
|
||||
TEST(code_zero_unscoped, "UNIT-POLICY-003", "Transport flood with code 0 is un-scoped, other codes and routes are not") {
|
||||
Packet p;
|
||||
p.transport_codes[1] = 0x5678;
|
||||
for (uint16_t code : {0x0000, 0x0001, 0xFFFE}) {
|
||||
p.transport_codes[0] = code;
|
||||
p.header = ROUTE_TYPE_TRANSPORT_FLOOD | (PAYLOAD_TYPE_TXT_MSG << 2);
|
||||
CHECK(isUnscopedFlood(&p) == (code == 0));
|
||||
p.setPathHashSizeAndCount(1, 3);
|
||||
CHECK(isFloodHopLimitExceeded(&p, 5, 3, 2) == (code == 0));
|
||||
p.setPathHashSizeAndCount(1, 0);
|
||||
CHECK(isFloodHopLimitExceeded(&p, 5, 0, 2) == (code == 0));
|
||||
p.header = ROUTE_TYPE_TRANSPORT_DIRECT | (PAYLOAD_TYPE_TXT_MSG << 2);
|
||||
CHECK(!isUnscopedFlood(&p));
|
||||
p.header = ROUTE_TYPE_FLOOD | (PAYLOAD_TYPE_TXT_MSG << 2);
|
||||
CHECK(isUnscopedFlood(&p));
|
||||
p.header = ROUTE_TYPE_DIRECT | (PAYLOAD_TYPE_TXT_MSG << 2);
|
||||
CHECK(!isUnscopedFlood(&p));
|
||||
}
|
||||
}
|
||||
TEST(rate_window, "UNIT-RATE-001", "Rate window threshold expiry and reset") {
|
||||
RateLimiter limiter(2, 10);
|
||||
CHECK(limiter.allow(100)); CHECK(limiter.allow(101));
|
||||
|
||||
@@ -33,7 +33,7 @@ list(APPEND BOARD_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
# Service advertises (CONFIG_BT_DIS_FW_REV_STR, generated from it below), what the
|
||||
# GitHub release is tagged/named, and what the Mesh America catalog uses as its
|
||||
# version key. The release workflow reads this line directly — keep its form.
|
||||
set(ZEPHCORE_FIRMWARE_VERSION "1.17.7-zephcore")
|
||||
set(ZEPHCORE_FIRMWARE_VERSION "1.18.0-zephcore")
|
||||
|
||||
# ========== Helpers ==========
|
||||
# Append FILE to the overlay list once, keeping its FIRST position. Position is
|
||||
|
||||
@@ -674,20 +674,21 @@ uint32_t RepeaterMesh::getDirectRetransmitDelay(const mesh::Packet* packet) {
|
||||
return computeAdaptiveDirectDelay(packet);
|
||||
}
|
||||
|
||||
// ZEPHCORE: ours. Also records whether the packet was an unscoped flood.
|
||||
// ZEPHCORE: ours. Also records whether the packet was an unscoped flood; a
|
||||
// transport flood with code 0 is one, wildcard deny included (UPSTREAM_TRACKER 01f9293b).
|
||||
mesh::DispatcherAction RepeaterMesh::onRecvPacket(mesh::Packet* pkt) {
|
||||
// Determine the request packet's region so sendFloodReply() can echo the same
|
||||
// scope. Runs for every packet (not just floods) so recv_pkt_region is cleared
|
||||
// for direct packets instead of inheriting the last flood's region.
|
||||
recv_pkt_unscoped_flood = (pkt->getRouteType() == ROUTE_TYPE_FLOOD);
|
||||
if (pkt->getRouteType() == ROUTE_TYPE_TRANSPORT_FLOOD) {
|
||||
recv_pkt_region = region_map.findMatch(pkt, REGION_DENY_FLOOD);
|
||||
} else if (pkt->getRouteType() == ROUTE_TYPE_FLOOD) {
|
||||
recv_pkt_unscoped_flood = mesh::isUnscopedFlood(pkt);
|
||||
if (recv_pkt_unscoped_flood) {
|
||||
if (region_map.getWildcard().flags & REGION_DENY_FLOOD) {
|
||||
recv_pkt_region = nullptr;
|
||||
} else {
|
||||
recv_pkt_region = ®ion_map.getWildcard();
|
||||
}
|
||||
} else if (pkt->getRouteType() == ROUTE_TYPE_TRANSPORT_FLOOD) {
|
||||
recv_pkt_region = region_map.findMatch(pkt, REGION_DENY_FLOOD);
|
||||
} else {
|
||||
recv_pkt_region = nullptr;
|
||||
}
|
||||
|
||||
@@ -354,20 +354,21 @@ bool RoomServerMesh::allowPacketForward(const mesh::Packet* /*packet*/) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ZEPHCORE: ours. Also records whether the packet was an unscoped flood.
|
||||
// ZEPHCORE: ours. Also records whether the packet was an unscoped flood; a
|
||||
// transport flood with code 0 is one, wildcard deny included (UPSTREAM_TRACKER 01f9293b).
|
||||
mesh::DispatcherAction RoomServerMesh::onRecvPacket(mesh::Packet* pkt) {
|
||||
// Determine the request packet's region so sendFloodReply() can echo the same
|
||||
// scope. Runs for every packet (not just floods) so recv_pkt_region is cleared
|
||||
// for direct packets instead of inheriting the last flood's region.
|
||||
recv_pkt_unscoped_flood = (pkt->getRouteType() == ROUTE_TYPE_FLOOD);
|
||||
if (pkt->getRouteType() == ROUTE_TYPE_TRANSPORT_FLOOD) {
|
||||
recv_pkt_region = region_map.findMatch(pkt, REGION_DENY_FLOOD);
|
||||
} else if (pkt->getRouteType() == ROUTE_TYPE_FLOOD) {
|
||||
recv_pkt_unscoped_flood = mesh::isUnscopedFlood(pkt);
|
||||
if (recv_pkt_unscoped_flood) {
|
||||
if (region_map.getWildcard().flags & REGION_DENY_FLOOD) {
|
||||
recv_pkt_region = nullptr;
|
||||
} else {
|
||||
recv_pkt_region = ®ion_map.getWildcard();
|
||||
}
|
||||
} else if (pkt->getRouteType() == ROUTE_TYPE_TRANSPORT_FLOOD) {
|
||||
recv_pkt_region = region_map.findMatch(pkt, REGION_DENY_FLOOD);
|
||||
} else {
|
||||
recv_pkt_region = nullptr;
|
||||
}
|
||||
@@ -1003,6 +1004,8 @@ void RoomServerMesh::handleCommand(uint32_t sender_timestamp, char* command, cha
|
||||
addSystemPost(msg);
|
||||
strcpy(reply, "OK");
|
||||
}
|
||||
} else if (memcmp(command, "set repeat on", 13) == 0) {
|
||||
strcpy(reply, "ERR - repeat now deprecated"); // a room server never forwards (upstream 8579c667, 481f72ca)
|
||||
} else {
|
||||
_cli.handleCommand(sender_timestamp, command, reply);
|
||||
}
|
||||
|
||||
@@ -189,6 +189,7 @@ int RegionMap::getTransportKeysFor(const RegionEntry& src, TransportKey dest[],
|
||||
}
|
||||
|
||||
RegionEntry* RegionMap::findMatch(mesh::Packet* packet, uint8_t mask) {
|
||||
if (packet->transport_codes[0] == 0) return &wildcard;
|
||||
for (int i = 0; i < num_regions; i++) {
|
||||
auto region = ®ions[i];
|
||||
if ((region->flags & mask) == 0) { // does region allow this? (per 'mask' param)
|
||||
|
||||
@@ -14,12 +14,22 @@
|
||||
|
||||
namespace mesh {
|
||||
|
||||
/**
|
||||
* An un-scoped flood: ROUTE_TYPE_FLOOD, or a transport flood whose first code
|
||||
* is 0 (no Region computes 0; upstream 01f9293b treats it as un-scoped).
|
||||
*/
|
||||
inline bool isUnscopedFlood(const Packet *packet)
|
||||
{
|
||||
return packet->getRouteType() == ROUTE_TYPE_FLOOD
|
||||
|| (packet->getRouteType() == ROUTE_TYPE_TRANSPORT_FLOOD && packet->transport_codes[0] == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a flood packet against the configured hop limits.
|
||||
*
|
||||
* @param packet inbound flood packet (caller has already checked isRouteFlood())
|
||||
* @param flood_max hop ceiling for any flood packet
|
||||
* @param flood_max_unscoped hop ceiling for un-scoped (ROUTE_TYPE_FLOOD) packets;
|
||||
* @param flood_max_unscoped hop ceiling for un-scoped packets (isUnscopedFlood());
|
||||
* may be clamped lower than scoped/transport floods
|
||||
* @param flood_max_advert hop ceiling for ADVERT floods, typically tighter still
|
||||
* so advert churn stays local
|
||||
@@ -31,7 +41,7 @@ inline bool isFloodHopLimitExceeded(const Packet *packet, uint8_t flood_max,
|
||||
uint8_t hops = packet->getPathHashCount();
|
||||
|
||||
if (hops >= flood_max) return true;
|
||||
if (packet->getRouteType() == ROUTE_TYPE_FLOOD && hops >= flood_max_unscoped) return true;
|
||||
if (isUnscopedFlood(packet) && hops >= flood_max_unscoped) return true;
|
||||
if (packet->getPayloadType() == PAYLOAD_TYPE_ADVERT && hops >= flood_max_advert) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ class Mesh : public Dispatcher {
|
||||
void removeSelfFromPath(Packet* packet);
|
||||
void routeDirectRecvAcks(Packet* packet, uint32_t delay_millis);
|
||||
//void routeRecvAcks(Packet* packet, uint32_t delay_millis);
|
||||
DispatcherAction forwardMultipartDirect(Packet* pkt);
|
||||
DispatcherAction forwardMultipartDirect(Packet* pkt, uint32_t delay_millis);
|
||||
|
||||
protected:
|
||||
// ZEPHCORE: adaptive contention window — dupe tracking, reactive backoff,
|
||||
|
||||
@@ -142,13 +142,14 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
|
||||
}
|
||||
|
||||
if (self_id.isHashMatch(pkt->path, pkt->getPathHashSize()) && allowPacketForward(pkt)) {
|
||||
uint32_t d = getDirectRetransmitDelay(pkt);
|
||||
if (pkt->getPayloadType() == PAYLOAD_TYPE_MULTIPART) {
|
||||
return forwardMultipartDirect(pkt);
|
||||
return forwardMultipartDirect(pkt, d);
|
||||
} else if (pkt->getPayloadType() == PAYLOAD_TYPE_ACK) {
|
||||
if (!_tables->wasSeen(pkt)) { // don't retransmit!
|
||||
_tables->markSeen(pkt);
|
||||
removeSelfFromPath(pkt);
|
||||
routeDirectRecvAcks(pkt, 0);
|
||||
routeDirectRecvAcks(pkt, d);
|
||||
}
|
||||
return ACTION_RELEASE;
|
||||
}
|
||||
@@ -157,7 +158,6 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
|
||||
_tables->markSeen(pkt);
|
||||
removeSelfFromPath(pkt);
|
||||
|
||||
uint32_t d = getDirectRetransmitDelay(pkt);
|
||||
return ACTION_RETRANSMIT_DELAYED(0, d); // Routed traffic is HIGHEST priority
|
||||
}
|
||||
}
|
||||
@@ -430,7 +430,7 @@ DispatcherAction Mesh::routeRecvPacket(Packet* packet) {
|
||||
return ACTION_RELEASE;
|
||||
}
|
||||
|
||||
DispatcherAction Mesh::forwardMultipartDirect(Packet* pkt) {
|
||||
DispatcherAction Mesh::forwardMultipartDirect(Packet* pkt, uint32_t delay_millis) {
|
||||
uint8_t remaining = pkt->payload[0] >> 4; // num of packets in this multipart sequence still to be sent
|
||||
uint8_t type = pkt->payload[0] & 0x0F;
|
||||
|
||||
@@ -444,7 +444,7 @@ DispatcherAction Mesh::forwardMultipartDirect(Packet* pkt) {
|
||||
if (!_tables->wasSeen(&tmp)) { // don't retransmit!
|
||||
_tables->markSeen(&tmp);
|
||||
removeSelfFromPath(&tmp);
|
||||
routeDirectRecvAcks(&tmp, ((uint32_t)remaining + 1) * 300); // expect multipart ACKs 300ms apart (x2)
|
||||
routeDirectRecvAcks(&tmp, delay_millis + ((uint32_t)remaining + 1) * 300); // expect multipart ACKs 300ms apart (x2)
|
||||
}
|
||||
}
|
||||
return ACTION_RELEASE;
|
||||
@@ -454,13 +454,13 @@ void Mesh::routeDirectRecvAcks(Packet* packet, uint32_t delay_millis) {
|
||||
if (!packet->isMarkedDoNotRetransmit()) {
|
||||
uint8_t extra = getExtraAckTransmitCount();
|
||||
while (extra > 0) {
|
||||
delay_millis += getDirectRetransmitDelay(packet) + 300;
|
||||
auto a1 = createMultiAck(packet->payload, packet->payload_len, extra);
|
||||
if (a1) {
|
||||
a1->path_len = Packet::copyPath(a1->path, packet->path, packet->path_len);
|
||||
a1->header &= ~PH_ROUTE_MASK;
|
||||
a1->header |= ROUTE_TYPE_DIRECT;
|
||||
sendPacket(a1, 0, delay_millis);
|
||||
delay_millis += 300;
|
||||
}
|
||||
extra--;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user