diff --git a/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt b/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt index d8e197e9..b516eb26 100644 --- a/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt +++ b/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt @@ -654,7 +654,7 @@ class ChatViewModel( // Merge nicknames from BLE and Wi‑Fi Aware to display names for all peers val bleNick = meshService.getPeerNicknames() - val awareNick = try { com.bitchat.android.wifiaware.WifiAwareController.getService()?.getPeerNicknames() } catch (_: Exception) { null } + val awareNick = try { com.bitchat.android.wifiaware.WifiAwareController.getService()?.getPeerNicknamesMap() } catch (_: Exception) { null } val mergedNick = if (awareNick != null) bleNick + awareNick.filterKeys { it !in bleNick || bleNick[it].isNullOrBlank() } else bleNick state.setPeerNicknames(mergedNick) diff --git a/app/src/main/java/com/bitchat/android/wifi-aware/WifiAwareMeshService.kt b/app/src/main/java/com/bitchat/android/wifi-aware/WifiAwareMeshService.kt index 5e3c3c1c..b507a3e9 100644 --- a/app/src/main/java/com/bitchat/android/wifi-aware/WifiAwareMeshService.kt +++ b/app/src/main/java/com/bitchat/android/wifi-aware/WifiAwareMeshService.kt @@ -826,24 +826,30 @@ class WifiAwareMeshService(private val context: Context) { } if (routedPeerId == null) { - routedPeerId = senderPeerHex - peerSockets[routedPeerId] = socket - } - Log.d(TAG, "RX: packet type=${pkt.type} from ${senderPeerHex.take(8)}… (bytes=${raw.size})") packetProcessor.processPacket(RoutedPacket(pkt, routedPeerId)) } - + + // Loop break -> disconnection + handlePeerDisconnection(initialLogicalPeerId, routedPeerId) socket.closeQuietly() - routedPeerId?.let { - peerSockets.remove(it) - peerManager.removePeer(it) + } + + private fun handlePeerDisconnection(initialId: String, routedId: String?) { + serviceScope.launch { + Log.w(TAG, "Cleaning up peer: $initialId / $routedId") + val possible = setOfNotNull(initialId, routedId).filter { it.isNotEmpty() && it != myPeerID } + possible.forEach { id -> + peerSockets.remove(id)?.closeQuietly() + serverSockets.remove(id)?.closeQuietly() + networkCallbacks.remove(id)?.let { runCatching { cm.unregisterNetworkCallback(it) } } + peerManager.removePeer(id) + } } } /** * Sends a broadcast message to all peers. - * * @param content Text content of the message * @param mentions Optional list of mentioned peer IDs * @param channel Optional channel name @@ -1160,15 +1166,43 @@ class WifiAwareMeshService(private val context: Context) { /** * @return the current IPv4/IPv6 address of a connected peer, if any. + * Prefers the scoped IPv6 address format. */ fun getDeviceAddressForPeer(peerID: String): String? = - peerSockets[peerID]?.inetAddress?.hostAddress + peerSockets[peerID]?.let { resolveScopedAddress(it) } + + /** + * Helper to resolve a scoped IPv6 address from a socket for UI display. + */ + private fun resolveScopedAddress(sock: Socket): String? { + val addr = sock.inetAddress as? Inet6Address ?: return sock.inetAddress?.hostAddress + if (addr.scopeId != 0 || addr.isLoopbackAddress) return addr.hostAddress + + // If address has no scope but we are on Aware (Link-Local fe80), attempt interface resolution + val iface = try { + val lp = cm.getLinkProperties(cm.activeNetwork) + lp?.interfaceName ?: "aware0" + } catch (_: Exception) { "aware0" } + + return "${addr.hostAddress}%$iface" + } /** * @return a mapping of peerID → connected device IP address for all active sockets. + * Results are formatted as scoped addresses if applicable. */ - fun getDeviceAddressToPeerMapping(): Map = - peerSockets.mapValues { it.value.inetAddress.hostAddress } + fun getDeviceAddressToPeerMapping(): Map { + val map = mutableMapOf() + peerSockets.forEach { (pid, sock) -> + map[pid] = resolveScopedAddress(sock) ?: "unknown" + } + return map + } + + /** + * @return map of peer ID to nickname, bridged for UI warning fix. + */ + fun getPeerNicknamesMap(): Map = peerManager.getAllPeerNicknames() /** Returns recently discovered peer IDs via Aware discovery (may not be connected). */ fun getDiscoveredPeerIds(): Set =