From 199b9a29d5378a168a2213c4d851cd423dc8fdbe Mon Sep 17 00:00:00 2001 From: andrekir Date: Wed, 23 Oct 2024 19:05:43 -0300 Subject: [PATCH] refactor: extract traceroute text from `MeshService` --- .../geeksville/mesh/model/RouteDiscovery.kt | 60 +++++++++++++++++++ .../geeksville/mesh/service/MeshService.kt | 52 ++-------------- 2 files changed, 64 insertions(+), 48 deletions(-) create mode 100644 app/src/main/java/com/geeksville/mesh/model/RouteDiscovery.kt diff --git a/app/src/main/java/com/geeksville/mesh/model/RouteDiscovery.kt b/app/src/main/java/com/geeksville/mesh/model/RouteDiscovery.kt new file mode 100644 index 000000000..77098f23d --- /dev/null +++ b/app/src/main/java/com/geeksville/mesh/model/RouteDiscovery.kt @@ -0,0 +1,60 @@ +package com.geeksville.mesh.model + +import com.geeksville.mesh.MeshProtos +import com.geeksville.mesh.MeshProtos.RouteDiscovery +import com.geeksville.mesh.Portnums + +val MeshProtos.MeshPacket.fullRouteDiscovery: RouteDiscovery? + get() = with(decoded) { + if (hasDecoded() && !wantResponse && portnum == Portnums.PortNum.TRACEROUTE_APP) { + runCatching { RouteDiscovery.parseFrom(payload).toBuilder() }.getOrNull()?.apply { + clearRoute() + addAllRoute(listOf(to) + routeList + from) + if (hopStart > 0 && snrBackList.size > 0) { // otherwise back route is invalid + clearRouteBack() + addAllRouteBack(listOf(from) + routeBackList + to) + } + }?.build() + } else { + null + } + } + +@Suppress("MagicNumber") +private fun formatTraceroutePath(nodesList: List, snrList: List): String { + // nodesList should include both origin and destination nodes + // origin will not have an SNR value, but destination should + val snrStr = if (snrList.size == nodesList.size - 1) { + snrList + } else { + // use unknown SNR for entire route if snrList has invalid size + List(nodesList.size - 1) { -128 } + }.map { snr -> + val str = if (snr == -128) "?" else "${snr / 4}" + "⇊ $str dB" + } + + return nodesList.map { userName -> + "■ $userName" + }.flatMapIndexed { i, nodeStr -> + if (i == 0) listOf(nodeStr) else listOf(snrStr[i - 1], nodeStr) + }.joinToString("\n") +} + +private fun RouteDiscovery.getTracerouteResponse( + getUser: (nodeNum: Int) -> String, +): String = buildString { + if (routeList.isNotEmpty()) { + append("Route traced toward destination:\n\n") + append(formatTraceroutePath(routeList.map(getUser), snrTowardsList)) + } + if (routeBackList.isNotEmpty()) { + append("\n\n") + append("Route traced back to us:\n\n") + append(formatTraceroutePath(routeBackList.map(getUser), snrBackList)) + } +} + +fun MeshProtos.MeshPacket.getTracerouteResponse( + getUser: (nodeNum: Int) -> String, +): String? = fullRouteDiscovery?.getTracerouteResponse(getUser) diff --git a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt index 3f8f6a299..5227d577d 100644 --- a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt +++ b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt @@ -28,6 +28,7 @@ import com.geeksville.mesh.database.entity.NodeEntity import com.geeksville.mesh.database.entity.Packet import com.geeksville.mesh.database.entity.toNodeInfo import com.geeksville.mesh.model.DeviceVersion +import com.geeksville.mesh.model.getTracerouteResponse import com.geeksville.mesh.repository.datastore.RadioConfigRepository import com.geeksville.mesh.repository.location.LocationRepository import com.geeksville.mesh.repository.network.MQTTRepository @@ -747,9 +748,9 @@ class MeshService : Service(), Logging { } Portnums.PortNum.TRACEROUTE_APP_VALUE -> { - if (data.wantResponse) return // ignore data from traceroute requests - val parsed = MeshProtos.RouteDiscovery.parseFrom(data.payload) - handleReceivedTraceroute(packet, parsed) + radioConfigRepository.setTracerouteResponse( + packet.getTracerouteResponse(::getUserName) + ) } else -> debug("No custom processing needed for ${data.portnumValue}") @@ -906,51 +907,6 @@ class MeshService : Service(), Logging { } } - @Suppress("MagicNumber") - private fun formatTraceroutePath(nodesList: List, snrList: List): String { - // nodesList should include both origin and destination nodes - // origin will not have an SNR value, but destination should - val snrStr = if (snrList.size == nodesList.size - 1) { - snrList - } else { - // use unknown SNR for entire route if snrList has invalid size - List(nodesList.size - 1) { -128 } - }.map { snr -> - val str = if (snr == -128) "?" else "${snr / 4}" - "⇊ $str dB" - } - - return nodesList.map { nodeId -> - "■ ${getUserName(nodeId)}" - }.flatMapIndexed { i, nodeStr -> - if (i == 0) listOf(nodeStr) else listOf(snrStr[i - 1], nodeStr) - }.joinToString("\n") - } - - private fun handleReceivedTraceroute(packet: MeshPacket, trace: MeshProtos.RouteDiscovery) { - val nodesToward = mutableListOf() - nodesToward.add(packet.to) - nodesToward += trace.routeList - nodesToward.add(packet.from) - - val nodesBack = mutableListOf() - if (packet.hopStart > 0 && trace.snrBackList.size > 0) { // otherwise back route is invalid - nodesBack.add(packet.from) - nodesBack += trace.routeBackList - nodesBack.add(packet.to) - } - - radioConfigRepository.setTracerouteResponse(buildString { - append("Route traced toward destination:\n\n") - append(formatTraceroutePath(nodesToward, trace.snrTowardsList)) - if (nodesBack.size > 0) { - append("\n\n") - append("Route traced back to us:\n\n") - append(formatTraceroutePath(nodesBack, trace.snrBackList)) - } - }) - } - // If apps try to send packets when our radio is sleeping, we queue them here instead private val offlineSentPackets = mutableListOf()