mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 12:05:20 +00:00
Fix wifi aware routing (#534)
* Background persistence (#505) * persistence step 1 * fix build * messages in the background work, notifications not yet * app state store * DM icon shows up * notification launches when app is closed! * keep ui updated * lifecycle fixes * extensive logging, maybe revert later * send nickname in announcement * quit in notification * setting in about sheet * fix quit bitchat * lifecycle fixes * power mode based on background state * stats for both direciotns * fix graph persistence * better counting * count per device * only compute when debug sheet is open? untested * fix read receipts * fix read receipts fully * fix unread badge if messages have been read in focus * foreground promotion fix * fix app kill in notification * adjust to new tor * nice * about sheet design * bump version 1.6.0 (#524) * Automated update of relay data - Sun Dec 14 06:06:53 UTC 2025 * bump targetSdk (#526) * Automated update of relay data - Sun Dec 21 06:06:56 UTC 2025 * Automated update of relay data - Sun Dec 28 06:07:12 UTC 2025 * Prevent quit notification from reappearing (#530) * shutdown sequence * Prevent quit notification from reappearing * Restrict force-finish broadcast * Cancel quit shutdown on relaunch * fix(wifi-aware): use bindSocket and scoped IPv6 instead of bindProcessToNetwork * Merge branch 'upstream/main' into fix/wifi-aware-socket-binding * 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. * Enhance Wi-Fi Aware robustness and debug UI display - Clean up transport resources (sockets, server sockets, network callbacks) immediately on peer disconnection. - Implement resolveScopedAddress to show scoped IPv6 (e.g., %aware0) in Debug UI. - Fix Map type mismatch warning in ChatViewModel bridge. - Filter self-ID from peer cleanup tables to prevent recursive self-removal. * Share GossipSyncManager across transports to prevent redundant message synchronization - Registered BluetoothMeshService's GossipSyncManager as a singleton in MeshServiceHolder. - Modified WifiAwareMeshService to use the shared GossipSyncManager if available. - Added background cleanup for peer mappings on socket disconnection. - Fixed Kotlin type mismatch during nickname map merging. * Restore VPN acquisition logic and improve peer cleanup - Revert removal of NET_CAPABILITY_NOT_VPN to allow hardware handle acquisition while VPN is active. - Refactor handlePeerDisconnection to more reliably cleanup initial and routed IDs. - Switch cleanup logging to debug level to reduce log noise. * fix wifi aware routing --------- Co-authored-by: GitHub Action <action@github.com> Co-authored-by: aidenvalue <>
This commit is contained in:
co-authored by
GitHub Action
aidenvalue <>
parent
bd272bb5ea
commit
c12af45b6b
@@ -13,6 +13,7 @@ import com.bitchat.android.protocol.SpecialRecipients
|
||||
import com.bitchat.android.model.RequestSyncPacket
|
||||
import com.bitchat.android.sync.GossipSyncManager
|
||||
import com.bitchat.android.util.toHexString
|
||||
import com.bitchat.android.service.TransportBridgeService
|
||||
import kotlinx.coroutines.*
|
||||
import java.util.*
|
||||
import kotlin.math.sign
|
||||
@@ -31,7 +32,7 @@ import kotlin.random.Random
|
||||
* - BluetoothConnectionManager: BLE connections and GATT operations
|
||||
* - PacketProcessor: Incoming packet routing
|
||||
*/
|
||||
class BluetoothMeshService(private val context: Context) {
|
||||
class BluetoothMeshService(private val context: Context) : TransportBridgeService.TransportLayer {
|
||||
private val debugManager by lazy { try { com.bitchat.android.ui.debug.DebugSettingsManager.getInstance() } catch (e: Exception) { null } }
|
||||
|
||||
companion object {
|
||||
@@ -101,9 +102,15 @@ class BluetoothMeshService(private val context: Context) {
|
||||
// Wire sync manager delegate
|
||||
gossipSyncManager.delegate = object : GossipSyncManager.Delegate {
|
||||
override fun sendPacket(packet: BitchatPacket) {
|
||||
connectionManager.broadcastPacket(RoutedPacket(packet))
|
||||
dispatchGlobal(RoutedPacket(packet))
|
||||
}
|
||||
override fun sendPacketToPeer(peerID: String, packet: BitchatPacket) {
|
||||
// Point-to-point optimization if possible, but for bridge safety
|
||||
// we might want to consider dispatchGlobal if peer is on another transport.
|
||||
// However, sendPacketToPeer in connectionManager is BLE-specific unicast.
|
||||
// If peer is on Wi-Fi, this won't reach.
|
||||
// For now, let's keep unicast as-is (it's mostly for sync)
|
||||
// and assume routing handles the rest via broadcasts if needed.
|
||||
connectionManager.sendPacketToPeer(peerID, packet)
|
||||
}
|
||||
override fun signPacketForBroadcast(packet: BitchatPacket): BitchatPacket {
|
||||
@@ -111,6 +118,26 @@ class BluetoothMeshService(private val context: Context) {
|
||||
}
|
||||
}
|
||||
Log.d(TAG, "Delegates set up; GossipSyncManager initialized")
|
||||
|
||||
// Register with cross-layer transport bridge
|
||||
TransportBridgeService.register("BLE", this)
|
||||
}
|
||||
|
||||
// TransportLayer implementation
|
||||
override fun send(packet: RoutedPacket) {
|
||||
// Received from bridge (e.g. Wi-Fi) -> Send via BLE
|
||||
// Direct injection prevents routing loops (bridge handles source check)
|
||||
connectionManager.broadcastPacket(packet)
|
||||
}
|
||||
|
||||
/**
|
||||
* unified dispatch: Send to local BLE and bridge to other transports
|
||||
*/
|
||||
private fun dispatchGlobal(routed: RoutedPacket) {
|
||||
// 1. Send to local BLE transport
|
||||
connectionManager.broadcastPacket(routed)
|
||||
// 2. Bridge to other transports (e.g. Wi-Fi)
|
||||
TransportBridgeService.broadcast("BLE", routed)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -164,8 +191,6 @@ class BluetoothMeshService(private val context: Context) {
|
||||
// PeerManager delegates to main mesh service delegate
|
||||
peerManager.delegate = object : PeerManagerDelegate {
|
||||
override fun onPeerListUpdated(peerIDs: List<String>) {
|
||||
// Update process-wide state first
|
||||
try { com.bitchat.android.services.AppStateStore.setPeers(peerIDs) } catch (_: Exception) { }
|
||||
// Then notify UI delegate if attached
|
||||
delegate?.didUpdatePeerList(peerIDs)
|
||||
}
|
||||
@@ -208,7 +233,7 @@ class BluetoothMeshService(private val context: Context) {
|
||||
)
|
||||
// Sign the handshake response
|
||||
val signedPacket = signPacketBeforeBroadcast(responsePacket)
|
||||
connectionManager.broadcastPacket(RoutedPacket(signedPacket))
|
||||
dispatchGlobal(RoutedPacket(signedPacket))
|
||||
Log.d(TAG, "Sent Noise handshake response to $peerID (${response.size} bytes)")
|
||||
}
|
||||
|
||||
@@ -228,7 +253,7 @@ class BluetoothMeshService(private val context: Context) {
|
||||
}
|
||||
|
||||
override fun sendPacket(packet: BitchatPacket) {
|
||||
connectionManager.broadcastPacket(RoutedPacket(packet))
|
||||
dispatchGlobal(RoutedPacket(packet))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,11 +297,11 @@ class BluetoothMeshService(private val context: Context) {
|
||||
// Sign the packet before broadcasting
|
||||
val signedPacket = signPacketBeforeBroadcast(packet)
|
||||
val routed = RoutedPacket(signedPacket)
|
||||
connectionManager.broadcastPacket(routed)
|
||||
dispatchGlobal(routed)
|
||||
}
|
||||
|
||||
override fun relayPacket(routed: RoutedPacket) {
|
||||
connectionManager.broadcastPacket(routed)
|
||||
dispatchGlobal(routed)
|
||||
}
|
||||
|
||||
override fun getBroadcastRecipient(): ByteArray {
|
||||
@@ -323,7 +348,7 @@ class BluetoothMeshService(private val context: Context) {
|
||||
|
||||
// Sign the handshake packet before broadcasting
|
||||
val signedPacket = signPacketBeforeBroadcast(packet)
|
||||
connectionManager.broadcastPacket(RoutedPacket(signedPacket))
|
||||
dispatchGlobal(RoutedPacket(signedPacket))
|
||||
Log.d(TAG, "Initiated Noise handshake with $peerID (${handshakeData.size} bytes)")
|
||||
} else {
|
||||
Log.w(TAG, "Failed to generate Noise handshake data for $peerID")
|
||||
@@ -515,7 +540,7 @@ class BluetoothMeshService(private val context: Context) {
|
||||
}
|
||||
|
||||
override fun relayPacket(routed: RoutedPacket) {
|
||||
connectionManager.broadcastPacket(routed)
|
||||
dispatchGlobal(routed)
|
||||
}
|
||||
|
||||
override fun handleRequestSync(routed: RoutedPacket) {
|
||||
@@ -632,6 +657,9 @@ class BluetoothMeshService(private val context: Context) {
|
||||
|
||||
Log.i(TAG, "Stopping Bluetooth mesh service")
|
||||
isActive = false
|
||||
|
||||
// Unregister from bridge
|
||||
TransportBridgeService.unregister("BLE")
|
||||
|
||||
// Send leave announcement
|
||||
sendLeaveAnnouncement()
|
||||
@@ -691,7 +719,7 @@ class BluetoothMeshService(private val context: Context) {
|
||||
|
||||
// Sign the packet before broadcasting
|
||||
val signedPacket = signPacketBeforeBroadcast(packet)
|
||||
connectionManager.broadcastPacket(RoutedPacket(signedPacket))
|
||||
dispatchGlobal(RoutedPacket(signedPacket))
|
||||
// Track our own broadcast message for sync
|
||||
try { gossipSyncManager.onPublicPacketSeen(signedPacket) } catch (_: Exception) { }
|
||||
}
|
||||
@@ -723,7 +751,7 @@ class BluetoothMeshService(private val context: Context) {
|
||||
val signed = signPacketBeforeBroadcast(packet)
|
||||
// Use a stable transferId based on the file TLV payload for progress tracking
|
||||
val transferId = sha256Hex(payload)
|
||||
connectionManager.broadcastPacket(RoutedPacket(signed, transferId = transferId))
|
||||
dispatchGlobal(RoutedPacket(signed, transferId = transferId))
|
||||
try { gossipSyncManager.onPublicPacketSeen(signed) } catch (_: Exception) { }
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
@@ -781,7 +809,7 @@ class BluetoothMeshService(private val context: Context) {
|
||||
val signed = signPacketBeforeBroadcast(packet)
|
||||
// Use a stable transferId based on the unencrypted file TLV payload for progress tracking
|
||||
val transferId = sha256Hex(filePayload)
|
||||
connectionManager.broadcastPacket(RoutedPacket(signed, transferId = transferId))
|
||||
dispatchGlobal(RoutedPacket(signed, transferId = transferId))
|
||||
Log.d(TAG, "✅ Sent encrypted file to $recipientPeerID")
|
||||
|
||||
} catch (e: Exception) {
|
||||
@@ -861,7 +889,7 @@ class BluetoothMeshService(private val context: Context) {
|
||||
|
||||
// Sign the packet before broadcasting
|
||||
val signedPacket = signPacketBeforeBroadcast(packet)
|
||||
connectionManager.broadcastPacket(RoutedPacket(signedPacket))
|
||||
dispatchGlobal(RoutedPacket(signedPacket))
|
||||
Log.d(TAG, "📤 Sent encrypted private message to $recipientPeerID (${encrypted.size} bytes)")
|
||||
|
||||
// FIXED: Don't send didReceiveMessage for our own sent messages
|
||||
@@ -932,7 +960,7 @@ class BluetoothMeshService(private val context: Context) {
|
||||
|
||||
// Sign the packet before broadcasting
|
||||
val signedPacket = signPacketBeforeBroadcast(packet)
|
||||
connectionManager.broadcastPacket(RoutedPacket(signedPacket))
|
||||
dispatchGlobal(RoutedPacket(signedPacket))
|
||||
Log.d(TAG, "📤 Sent read receipt to $recipientPeerID for message $messageID")
|
||||
|
||||
// Persist as read after successful send
|
||||
@@ -986,7 +1014,7 @@ class BluetoothMeshService(private val context: Context) {
|
||||
announcePacket.copy(signature = signature)
|
||||
} ?: announcePacket
|
||||
|
||||
connectionManager.broadcastPacket(RoutedPacket(signedPacket))
|
||||
dispatchGlobal(RoutedPacket(signedPacket))
|
||||
Log.d(TAG, "Sent iOS-compatible signed TLV announce (${tlvPayload.size} bytes)")
|
||||
// Track announce for sync
|
||||
try { gossipSyncManager.onPublicPacketSeen(signedPacket) } catch (_: Exception) { }
|
||||
@@ -1035,7 +1063,7 @@ class BluetoothMeshService(private val context: Context) {
|
||||
packet.copy(signature = signature)
|
||||
} ?: packet
|
||||
|
||||
connectionManager.broadcastPacket(RoutedPacket(signedPacket))
|
||||
dispatchGlobal(RoutedPacket(signedPacket))
|
||||
peerManager.markPeerAsAnnouncedTo(peerID)
|
||||
Log.d(TAG, "Sent iOS-compatible signed TLV peer announce to $peerID (${tlvPayload.size} bytes)")
|
||||
|
||||
@@ -1056,7 +1084,7 @@ class BluetoothMeshService(private val context: Context) {
|
||||
|
||||
// Sign the packet before broadcasting
|
||||
val signedPacket = signPacketBeforeBroadcast(packet)
|
||||
connectionManager.broadcastPacket(RoutedPacket(signedPacket))
|
||||
dispatchGlobal(RoutedPacket(signedPacket))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user