diff --git a/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt b/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt index e9dd4f8e..4e8b3a43 100644 --- a/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt +++ b/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt @@ -158,9 +158,11 @@ class BluetoothMeshService(private val context: Context) { */ private fun setupDelegates() { Log.d(TAG, "Setting up component delegates") - // Provide nickname resolver to BLE broadcaster for detailed logs + // Provide nickname resolver to BLE broadcaster and debug manager try { - connectionManager.setNicknameResolver { pid -> peerManager.getPeerNickname(pid) } + val resolver: (String) -> String? = { pid -> peerManager.getPeerNickname(pid) } + connectionManager.setNicknameResolver(resolver) + debugManager?.setNicknameResolver(resolver) } catch (_: Exception) { } // PeerManager delegates to main mesh service delegate peerManager.delegate = object : PeerManagerDelegate { @@ -546,21 +548,12 @@ class BluetoothMeshService(private val context: Context) { override fun onPacketReceived(packet: BitchatPacket, peerID: String, device: android.bluetooth.BluetoothDevice?) { // Log incoming for debug graphs (do not double-count anywhere else) try { - val nick = getPeerNicknames()[peerID] - val route = packet.route - val routeInfo = if (!route.isNullOrEmpty()) "routed: ${route.size} hops" else null - - // Convert route to hex strings for visualization - val routeStrings = route?.map { it.toHexString() } - com.bitchat.android.ui.debug.DebugSettingsManager.getInstance().logIncoming( - packetType = packet.type.toString(), + packet = packet, fromPeerID = peerID, - fromNickname = nick, + fromNickname = null, fromDeviceAddress = device?.address, - packetVersion = packet.version, - routeInfo = routeInfo, - route = routeStrings + myPeerID = myPeerID ) } catch (_: Exception) { } packetProcessor.processPacket(RoutedPacket(packet, peerID, device?.address)) diff --git a/app/src/main/java/com/bitchat/android/mesh/PacketProcessor.kt b/app/src/main/java/com/bitchat/android/mesh/PacketProcessor.kt index 54d006b9..fb47f40f 100644 --- a/app/src/main/java/com/bitchat/android/mesh/PacketProcessor.kt +++ b/app/src/main/java/com/bitchat/android/mesh/PacketProcessor.kt @@ -78,8 +78,6 @@ class PacketProcessor(private val myPeerID: String) { Log.w(TAG, "Received packet with no peer ID, skipping") return } - - // Get or create actor for this peer val actor = actors.getOrPut(peerID) { getOrCreateActorForPeer(peerID) } diff --git a/app/src/main/java/com/bitchat/android/ui/debug/DebugSettingsManager.kt b/app/src/main/java/com/bitchat/android/ui/debug/DebugSettingsManager.kt index d04a2f3e..04341fa5 100644 --- a/app/src/main/java/com/bitchat/android/ui/debug/DebugSettingsManager.kt +++ b/app/src/main/java/com/bitchat/android/ui/debug/DebugSettingsManager.kt @@ -7,6 +7,8 @@ import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow import java.util.Date import java.util.concurrent.ConcurrentLinkedQueue +import com.bitchat.android.protocol.BitchatPacket +import com.bitchat.android.util.toHexString /** * Debug settings manager for controlling debug features and collecting debug data @@ -485,20 +487,32 @@ class DebugSettingsManager private constructor() { } } + // Peer nickname resolver + private var nicknameResolver: ((String) -> String?)? = null + fun setNicknameResolver(resolver: (String) -> String?) { nicknameResolver = resolver } + // Explicit incoming/outgoing logging to avoid double counting - fun logIncoming(packetType: String, fromPeerID: String?, fromNickname: String?, fromDeviceAddress: String?, packetVersion: UByte = 1u, routeInfo: String? = null, route: List? = null) { + fun logIncoming(packet: BitchatPacket, fromPeerID: String, fromNickname: String?, fromDeviceAddress: String?, myPeerID: String) { + val packetType = packet.type.toString() + val packetVersion = packet.version + val route = packet.route + val routeInfo = if (!route.isNullOrEmpty()) "routed: ${route.size} hops" else null + if (verboseLoggingEnabled.value) { - val who = fromNickname ?: fromPeerID ?: "unknown" + val resolvedNick = fromNickname ?: nicknameResolver?.invoke(fromPeerID) ?: "unknown" + val who = if (resolvedNick != "unknown") "$resolvedNick ($fromPeerID)" else fromPeerID val routeStr = if (routeInfo != null) " $routeInfo" else "" - addDebugMessage(DebugMessage.PacketEvent("📥 Incoming v$packetVersion $packetType from $who (${fromPeerID ?: "?"}, ${fromDeviceAddress ?: "?"})$routeStr")) + addDebugMessage(DebugMessage.PacketEvent("📥 Incoming v$packetVersion $packetType from $who (${fromDeviceAddress ?: "?"})$routeStr")) } - // Emit visual events - if (fromPeerID != null) { - emitVisualEvent(MeshVisualEvent.PacketActivity(fromPeerID)) - } + emitVisualEvent(MeshVisualEvent.PacketActivity(fromPeerID)) + if (!route.isNullOrEmpty()) { - emitVisualEvent(MeshVisualEvent.RouteActivity(route)) + val fullRoute = mutableListOf() + fullRoute.add(packet.senderID.toHexString()) + route.forEach { fullRoute.add(it.toHexString()) } + packet.recipientID?.let { fullRoute.add(it.toHexString()) } + emitVisualEvent(MeshVisualEvent.RouteActivity(fullRoute)) } val now = System.currentTimeMillis() @@ -509,11 +523,11 @@ class DebugSettingsManager private constructor() { deviceIncomingTotalsMap[it] = (deviceIncomingTotalsMap[it] ?: 0L) + 1L _perDeviceIncomingTotalsFlow.value = deviceIncomingTotalsMap.toMap() } - fromPeerID?.let { - perPeerIncoming.getOrPut(it) { ConcurrentLinkedQueue() }.offer(now) - peerIncomingTotalsMap[it] = (peerIncomingTotalsMap[it] ?: 0L) + 1L - _perPeerIncomingTotalsFlow.value = peerIncomingTotalsMap.toMap() - } + + perPeerIncoming.getOrPut(fromPeerID) { ConcurrentLinkedQueue() }.offer(now) + peerIncomingTotalsMap[fromPeerID] = (peerIncomingTotalsMap[fromPeerID] ?: 0L) + 1L + _perPeerIncomingTotalsFlow.value = peerIncomingTotalsMap.toMap() + // bump totals val cur = _relayStats.value _relayStats.value = cur.copy(