From 2b6c3185b08e3ef493e09d88ea451cff2e3152c6 Mon Sep 17 00:00:00 2001 From: James Rich <2199651+jamesarich@users.noreply.github.com> Date: Mon, 26 Jan 2026 11:50:04 -0600 Subject: [PATCH] fix(mesh): Set `hopStart` to match `hopLimit` in sent packets (#4324) Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com> --- .../mesh/service/MeshCommandSender.kt | 8 ++++--- .../service/MeshCommandSenderHopLimitTest.kt | 22 +++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/service/MeshCommandSender.kt b/app/src/main/java/com/geeksville/mesh/service/MeshCommandSender.kt index 4e078e7f1..ab901dd66 100644 --- a/app/src/main/java/com/geeksville/mesh/service/MeshCommandSender.kt +++ b/app/src/main/java/com/geeksville/mesh/service/MeshCommandSender.kt @@ -100,7 +100,7 @@ constructor( sessionPasskey.set(key) } - private fun getHopLimit(): Int = localConfig.value.lora.hopLimit.takeIf { it > 0 } ?: DEFAULT_HOP_LIMIT + private fun computeHopLimit(): Int = localConfig.value.lora.hopLimit.takeIf { it > 0 } ?: DEFAULT_HOP_LIMIT private fun getAdminChannelIndex(toNum: Int): Int { val myNum = nodeManager?.myNodeNum ?: return 0 @@ -147,7 +147,7 @@ constructor( newMeshPacketTo(p.to ?: DataPacket.ID_BROADCAST).buildMeshPacket( id = p.id, wantAck = p.wantAck, - hopLimit = if (p.hopLimit > 0) p.hopLimit else getHopLimit(), + hopLimit = if (p.hopLimit > 0) p.hopLimit else computeHopLimit(), channel = p.channel, ) { portnumValue = p.dataType @@ -395,7 +395,9 @@ constructor( ): MeshPacket { this.id = id this.wantAck = wantAck - this.hopLimit = if (hopLimit > 0) hopLimit else getHopLimit() + val actualHopLimit = if (hopLimit > 0) hopLimit else computeHopLimit() + this.hopLimit = actualHopLimit + this.hopStart = actualHopLimit this.priority = priority if (channel == DataPacket.PKC_CHANNEL_INDEX) { diff --git a/app/src/test/java/com/geeksville/mesh/service/MeshCommandSenderHopLimitTest.kt b/app/src/test/java/com/geeksville/mesh/service/MeshCommandSenderHopLimitTest.kt index f9502b066..0ddb5703c 100644 --- a/app/src/test/java/com/geeksville/mesh/service/MeshCommandSenderHopLimitTest.kt +++ b/app/src/test/java/com/geeksville/mesh/service/MeshCommandSenderHopLimitTest.kt @@ -56,6 +56,7 @@ class MeshCommandSenderHopLimitTest { commandSender = MeshCommandSender(packetHandler, nodeManager, connectionStateHolder, radioConfigRepository) commandSender.start(testScope) + nodeManager.myNodeNum = 123 } @Test @@ -81,6 +82,7 @@ class MeshCommandSenderHopLimitTest { val capturedHopLimit = meshPacketSlot.captured.hopLimit assertTrue("Hop limit should be greater than 0, but was $capturedHopLimit", capturedHopLimit > 0) assertEquals(3, capturedHopLimit) + assertEquals(3, meshPacketSlot.captured.hopStart) } @Test @@ -97,5 +99,25 @@ class MeshCommandSenderHopLimitTest { verify { packetHandler.sendToRadio(any()) } assertEquals(7, meshPacketSlot.captured.hopLimit) + assertEquals(7, meshPacketSlot.captured.hopStart) + } + + @Test + fun `requestUserInfo sets hopStart equal to hopLimit`() = runTest(testDispatcher) { + val destNum = 12345 + val meshPacketSlot = slot() + every { packetHandler.sendToRadio(capture(meshPacketSlot)) } returns Unit + + localConfigFlow.value = + LocalConfig.newBuilder().setLora(Config.LoRaConfig.newBuilder().setHopLimit(6)).build() + + // Mock node manager interactions + nodeManager.nodeDBbyNodeNum.remove(destNum) + + commandSender.requestUserInfo(destNum) + + verify { packetHandler.sendToRadio(any()) } + assertEquals("Hop Limit should be 6", 6, meshPacketSlot.captured.hopLimit) + assertEquals("Hop Start should be 6", 6, meshPacketSlot.captured.hopStart) } }