Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions src/mesh/MeshService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,10 @@ int MeshService::handleFromRadio(const meshtastic_MeshPacket *mp)
}

printPacket("Forwarding to phone", mp);
sendToPhone(packetPool.allocCopy(*mp));
if (auto *c = packetPool.allocCopy(*mp))
sendToPhone(c);
else
LOG_WARN("phone-forward dropped: packetPool exhausted");

return 0;
}
Expand Down Expand Up @@ -205,7 +208,10 @@ void MeshService::handleToRadio(meshtastic_MeshPacket &p)
DEBUG_HEAP_BEFORE;
auto a = packetPool.allocCopy(p);
DEBUG_HEAP_AFTER("MeshService::handleToRadio", a);
sendToMesh(a, RX_SRC_USER);
if (a)
sendToMesh(a, RX_SRC_USER);
else
LOG_WARN("handleToRadio: packetPool exhausted, dropping ToRadio packet");

bool loopback = false; // if true send any packet the phone sends back itself (for testing)
if (loopback) {
Expand All @@ -225,6 +231,10 @@ bool MeshService::cancelSending(PacketId id)
ErrorCode MeshService::sendQueueStatusToPhone(const meshtastic_QueueStatus &qs, ErrorCode res, uint32_t mesh_packet_id)
{
meshtastic_QueueStatus *copied = queueStatusPool.allocCopy(qs);
if (!copied) {
LOG_WARN("sendQueueStatusToPhone: queueStatusPool exhausted, skipping");
return ERRNO_UNKNOWN;
}

copied->res = res;
copied->mesh_packet_id = mesh_packet_id;
Expand Down Expand Up @@ -265,7 +275,10 @@ void MeshService::sendToMesh(meshtastic_MeshPacket *p, RxSource src, bool ccToPh
auto a = packetPool.allocCopy(*p);
DEBUG_HEAP_AFTER("MeshService::sendToMesh", a);

sendToPhone(a);
if (a)
sendToPhone(a);
// else: pool exhausted; phone will see this packet again via the
// normal RX-to-phone path on a future cycle.
}

// Router may ask us to release the packet if it wasn't sent
Expand Down
17 changes: 12 additions & 5 deletions src/mesh/NextHopRouter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@ ErrorCode NextHopRouter::send(meshtastic_MeshPacket *p)

// If it's from us, ReliableRouter already handles retransmissions if want_ack is set. If a next hop is set and hop limit is
// not 0 or want_ack is set, start retransmissions
if ((!isFromUs(p) || !p->want_ack) && p->next_hop != NO_NEXT_HOP_PREFERENCE && (p->hop_limit > 0 || p->want_ack))
startRetransmission(packetPool.allocCopy(*p)); // start retransmission for relayed packet
if ((!isFromUs(p) || !p->want_ack) && p->next_hop != NO_NEXT_HOP_PREFERENCE && (p->hop_limit > 0 || p->want_ack)) {
if (auto *retxCopy = packetPool.allocCopy(*p))
startRetransmission(retxCopy); // start retransmission for relayed packet
// else: pool exhausted; relayed packet is still sent below — just no retransmission
}

return Router::send(p);
}
Expand Down Expand Up @@ -146,6 +149,10 @@ bool NextHopRouter::perhapsRebroadcast(const meshtastic_MeshPacket *p)
if (isRebroadcaster()) {
if (p->next_hop == NO_NEXT_HOP_PREFERENCE || p->next_hop == nodeDB->getLastByteOfNodeNum(getNodeNum())) {
meshtastic_MeshPacket *tosend = packetPool.allocCopy(*p); // keep a copy because we will be sending it
if (!tosend) {
LOG_WARN("Rebroadcast skipped: packetPool exhausted (from=%x)", p->relay_node);
return false;
}
LOG_INFO("Rebroadcast received message coming from %x", p->relay_node);

// If exhausting hops, force hop_limit = 0 regardless of other logic
Expand Down Expand Up @@ -319,14 +326,14 @@ int32_t NextHopRouter::doRetransmissions()
LOG_INFO("Resetting next hop for packet with dest 0x%x\n", p.packet->to);
sentTo->next_hop = NO_NEXT_HOP_PREFERENCE;
}
FloodingRouter::send(packetPool.allocCopy(*p.packet));
if (auto *c = packetPool.allocCopy(*p.packet)) FloodingRouter::send(c);
} else {
NextHopRouter::send(packetPool.allocCopy(*p.packet));
if (auto *c = packetPool.allocCopy(*p.packet)) NextHopRouter::send(c);
}
} else {
// Note: we call the superclass version because we don't want to have our version of send() add a new
// retransmission record
FloodingRouter::send(packetPool.allocCopy(*p.packet));
if (auto *c = packetPool.allocCopy(*p.packet)) FloodingRouter::send(c);
}

// Queue again
Expand Down
4 changes: 3 additions & 1 deletion src/mesh/ReliableRouter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ ErrorCode ReliableRouter::send(meshtastic_MeshPacket *p)
auto copy = packetPool.allocCopy(*p);
DEBUG_HEAP_AFTER("ReliableRouter::send", copy);

startRetransmission(copy, NUM_RELIABLE_RETX);
if (copy)
startRetransmission(copy, NUM_RELIABLE_RETX);
// else: pool exhausted; the packet itself is still sent — just no retry
}

/* If we have pending retransmissions, add the airtime of this packet to it, because during that time we cannot receive an
Expand Down
9 changes: 6 additions & 3 deletions src/mesh/Router.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -384,12 +384,15 @@ ErrorCode Router::send(meshtastic_MeshPacket *p)
return encodeResult; // FIXME - this isn't a valid ErrorCode
}
#if !MESHTASTIC_EXCLUDE_MQTT
// Only publish to MQTT if we're the original transmitter of the packet
if (moduleConfig.mqtt.enabled && isFromUs(p) && mqtt) {
// Only publish to MQTT if we're the original transmitter of the packet.
// Skip on packetPool exhaustion (p_decoded == nullptr) — onSend would
// dereference the reference and crash; better to drop the MQTT publish
// for this one packet than panic the radio.
if (p_decoded && moduleConfig.mqtt.enabled && isFromUs(p) && mqtt) {
mqtt->onSend(*p, *p_decoded, chIndex);
}
#endif
packetPool.release(p_decoded);
packetPool.release(p_decoded); // release() handles nullptr
}

#if HAS_UDP_MULTICAST
Expand Down
4 changes: 4 additions & 0 deletions src/modules/AtakPluginModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,10 @@ void AtakPluginModule::alterReceivedProtobuf(meshtastic_MeshPacket &mp, meshtast
}
}
auto decompressedCopy = packetPool.allocCopy(mp);
if (!decompressedCopy) {
LOG_WARN("AtakPluginModule: packetPool exhausted, skipping decompressed phone forward");
return;
}
decompressedCopy->decoded.payload.size =
pb_encode_to_bytes(decompressedCopy->decoded.payload.bytes, sizeof(decompressedCopy->decoded.payload),
meshtastic_TAKPacket_fields, &uncompressed);
Expand Down
13 changes: 8 additions & 5 deletions src/modules/NodeInfoModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,15 @@ bool NodeInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
// if user has changed while packet was not for us, inform phone
if (hasChanged && !wasBroadcast && !isToUs(&mp)) {
auto packetCopy = packetPool.allocCopy(mp); // Keep a copy of the packet for later analysis
if (packetCopy) {
// Re-encode the user protobuf, as we have stripped out the user.id
packetCopy->decoded.payload.size = pb_encode_to_bytes(
packetCopy->decoded.payload.bytes, sizeof(packetCopy->decoded.payload.bytes), &meshtastic_User_msg, &p);

// Re-encode the user protobuf, as we have stripped out the user.id
packetCopy->decoded.payload.size = pb_encode_to_bytes(
packetCopy->decoded.payload.bytes, sizeof(packetCopy->decoded.payload.bytes), &meshtastic_User_msg, &p);

service->sendToPhone(packetCopy);
service->sendToPhone(packetCopy);
} else {
LOG_WARN("NodeInfoModule: packetPool exhausted, skipping phone forward");
}
}

pruneLastNodeInfoCache();
Expand Down