Fix Wi-Fi Aware connectivity and UI integration post-merge

- Replace bindProcessToNetwork with bindSocket for VPN compatibility.
- Implement Scoped IPv6 address resolution (aware0) for mesh routing.
- Bridge Wi-Fi Aware incoming messages to AppStateStore for UI visibility.
- Fix syntax errors and variable name conflicts in Debug UI.
This commit is contained in:
aidenvalue
2026-01-03 14:22:40 +01:00
parent 64f73df362
commit a511945838
4 changed files with 33 additions and 32 deletions
@@ -170,6 +170,13 @@ class MainActivity : OrientationAwareActivity() {
if (running && svc != null) { if (running && svc != null) {
svc.delegate = object : com.bitchat.android.wifiaware.WifiAwareMeshDelegate { svc.delegate = object : com.bitchat.android.wifiaware.WifiAwareMeshDelegate {
override fun didReceiveMessage(message: com.bitchat.android.model.BitchatMessage) { override fun didReceiveMessage(message: com.bitchat.android.model.BitchatMessage) {
if (message.isPrivate) {
message.senderPeerID?.let { pid -> com.bitchat.android.services.AppStateStore.addPrivateMessage(pid, message) }
} else if (message.channel != null) {
com.bitchat.android.services.AppStateStore.addChannelMessage(message.channel, message)
} else {
com.bitchat.android.services.AppStateStore.addPublicMessage(message)
}
chatViewModel.didReceiveMessage(message) chatViewModel.didReceiveMessage(message)
} }
override fun didUpdatePeerList(peers: List<String>) { override fun didUpdatePeerList(peers: List<String>) {
@@ -36,9 +36,6 @@ class DebugSettingsManager private constructor() {
private val _packetRelayEnabled = MutableStateFlow(true) private val _packetRelayEnabled = MutableStateFlow(true)
val packetRelayEnabled: StateFlow<Boolean> = _packetRelayEnabled.asStateFlow() val packetRelayEnabled: StateFlow<Boolean> = _packetRelayEnabled.asStateFlow()
private val _packetRelayEnabled = MutableStateFlow(true)
val packetRelayEnabled: StateFlow<Boolean> = _packetRelayEnabled.asStateFlow()
// Master transport toggles // Master transport toggles
private val _bleEnabled = MutableStateFlow(true) private val _bleEnabled = MutableStateFlow(true)
val bleEnabled: StateFlow<Boolean> = _bleEnabled.asStateFlow() val bleEnabled: StateFlow<Boolean> = _bleEnabled.asStateFlow()
@@ -52,7 +52,7 @@ fun DebugSettingsSheet(
val verboseLogging by manager.verboseLoggingEnabled.collectAsState() val verboseLogging by manager.verboseLoggingEnabled.collectAsState()
val gattServerEnabled by manager.gattServerEnabled.collectAsState() val gattServerEnabled by manager.gattServerEnabled.collectAsState()
val gattClientEnabled by manager.gattClientEnabled.collectAsState() val gattClientEnabled by manager.gattClientEnabled.collectAsState()
val packetRelayEnabled by manager.packetRelayEnabled.collectAsState() val packetRelayed by manager.packetRelayEnabled.collectAsState()
val maxOverall by manager.maxConnectionsOverall.collectAsState() val maxOverall by manager.maxConnectionsOverall.collectAsState()
val maxServer by manager.maxServerConnections.collectAsState() val maxServer by manager.maxServerConnections.collectAsState()
val maxClient by manager.maxClientConnections.collectAsState() val maxClient by manager.maxClientConnections.collectAsState()
@@ -280,7 +280,7 @@ fun DebugSettingsSheet(
Icon(Icons.Filled.PowerSettingsNew, contentDescription = null, tint = Color(0xFFFF9500)) Icon(Icons.Filled.PowerSettingsNew, contentDescription = null, tint = Color(0xFFFF9500))
Text(stringResource(R.string.debug_packet_relay), fontFamily = FontFamily.Monospace, fontSize = 14.sp, fontWeight = FontWeight.Medium) Text(stringResource(R.string.debug_packet_relay), fontFamily = FontFamily.Monospace, fontSize = 14.sp, fontWeight = FontWeight.Medium)
Spacer(Modifier.weight(1f)) Spacer(Modifier.weight(1f))
Switch(checked = packetRelayEnabled, onCheckedChange = { manager.setPacketRelayEnabled(it) }) Switch(checked = packetRelayed, onCheckedChange = { manager.setPacketRelayEnabled(it) })
} }
// Removed aggregate labels; we will show per-direction compact labels below titles // Removed aggregate labels; we will show per-direction compact labels below titles
// Toggle: overall vs per-connection vs per-peer // Toggle: overall vs per-connection vs per-peer
@@ -619,7 +619,7 @@ class WifiAwareMeshService(private val context: Context) {
} }
override fun onLost(network: Network) { override fun onLost(network: Network) {
networkCallbacks.remove(peerId) networkCallbacks.remove(peerId)
Log.d(TAG, "SERVER: network lost for \${peerId.take(8)}…") Log.d(TAG, "SERVER: network lost for ${peerId.take(8)}")
} }
} }
@@ -656,11 +656,13 @@ class WifiAwareMeshService(private val context: Context) {
) { ) {
// TCP keep-alive pings // TCP keep-alive pings
serviceScope.launch { serviceScope.launch {
val os = client.getOutputStream() try {
while (peerSockets.containsKey(peerId)) { val os = client.getOutputStream()
try { os.write(0) } catch (_: IOException) { break } while (peerSockets.containsKey(peerId)) {
delay(2_000) try { os.write(0) } catch (_: IOException) { break }
} delay(2_000)
}
} catch (_: Exception) {}
} }
// Discovery keep-alive // Discovery keep-alive
serviceScope.launch { serviceScope.launch {
@@ -711,14 +713,7 @@ class WifiAwareMeshService(private val context: Context) {
override fun onCapabilitiesChanged(network: Network, nc: NetworkCapabilities) { override fun onCapabilitiesChanged(network: Network, nc: NetworkCapabilities) {
if (peerSockets.containsKey(peerId)) return if (peerSockets.containsKey(peerId)) return
val info = (nc.transportInfo as? WifiAwareNetworkInfo) ?: return val info = (nc.transportInfo as? WifiAwareNetworkInfo) ?: return
val addr = info.peerIpv6Addr as Inet6Address val addr = info.peerIpv6Addr as? Inet6Address ?: return
val lp = cm.getLinkProperties(network)
val iface = lp?.interfaceName
try {
val sock = Socket()
network.bindSocket(sock)
val lp = cm.getLinkProperties(network) val lp = cm.getLinkProperties(network)
val iface = lp?.interfaceName val iface = lp?.interfaceName
@@ -731,13 +726,17 @@ class WifiAwareMeshService(private val context: Context) {
// Use scoped IPv6 if interface name is available // Use scoped IPv6 if interface name is available
val scopedAddr = if (iface != null && addr.scopeId == 0) { val scopedAddr = if (iface != null && addr.scopeId == 0) {
Inet6Address.getByAddress(null, addr.address, java.net.NetworkInterface.getByName(iface)) try {
Inet6Address.getByAddress(null, addr.address, java.net.NetworkInterface.getByName(iface))
} catch (e: Exception) {
addr
}
} else { } else {
addr addr
} }
sock.connect(java.net.InetSocketAddress(scopedAddr, port), 7000) sock.connect(java.net.InetSocketAddress(scopedAddr, port), 7000)
Log.d(TAG, "CLIENT: TCP connected to \${peerId.take(8)}… addr=\$scopedAddr:\$port (iface=\$iface)") Log.d(TAG, "CLIENT: TCP connected to ${peerId.take(8)}… addr=$scopedAddr:$port (iface=$iface)")
peerSockets[peerId] = sock peerSockets[peerId] = sock
try { peerManager.setDirectConnection(peerId, true) } catch (_: Exception) {} try { peerManager.setDirectConnection(peerId, true) } catch (_: Exception) {}
@@ -776,11 +775,13 @@ class WifiAwareMeshService(private val context: Context) {
) { ) {
// TCP keep-alive // TCP keep-alive
serviceScope.launch { serviceScope.launch {
val os = sock.getOutputStream() try {
while (peerSockets.containsKey(peerId)) { val os = sock.getOutputStream()
try { os.write(0) } catch (_: IOException) { break } while (peerSockets.containsKey(peerId)) {
delay(2_000) try { os.write(0) } catch (_: IOException) { break }
} delay(2_000)
}
} catch (_: Exception) {}
} }
// Discovery keep-alive // Discovery keep-alive
serviceScope.launch { serviceScope.launch {
@@ -1047,9 +1048,7 @@ class WifiAwareMeshService(private val context: Context) {
senderID = myPeerID, senderID = myPeerID,
payload = tlvPayload payload = tlvPayload
) )
val signed = encryptionService.signData(announcePacket.toBinaryDataForSigning()!!)?.let { val signed = signPacketBeforeBroadcast(announcePacket)
announcePacket.copy(signature = it)
} ?: announcePacket
broadcastPacket(RoutedPacket(signed)) broadcastPacket(RoutedPacket(signed))
try { gossipSyncManager.onPublicPacketSeen(signed) } catch (_: Exception) { } try { gossipSyncManager.onPublicPacketSeen(signed) } catch (_: Exception) { }
@@ -1074,9 +1073,7 @@ class WifiAwareMeshService(private val context: Context) {
senderID = myPeerID, senderID = myPeerID,
payload = tlvPayload payload = tlvPayload
) )
val signed = encryptionService.signData(packet.toBinaryDataForSigning()!!)?.let { val signed = signPacketBeforeBroadcast(packet)
packet.copy(signature = it)
} ?: packet
broadcastPacket(RoutedPacket(signed)) broadcastPacket(RoutedPacket(signed))
peerManager.markPeerAsAnnouncedTo(peerID) peerManager.markPeerAsAnnouncedTo(peerID)