mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 18:25:21 +00:00
werk
This commit is contained in:
@@ -73,6 +73,8 @@ class MainActivity : OrientationAwareActivity() {
|
||||
permissionManager = PermissionManager(this)
|
||||
// Initialize core mesh service first
|
||||
meshService = BluetoothMeshService(this)
|
||||
// Expose BLE mesh to Wi‑Fi Aware controller for cross-transport relays
|
||||
try { com.bitchat.android.wifiaware.WifiAwareController.setBleMeshService(meshService) } catch (_: Exception) { }
|
||||
bluetoothStatusManager = BluetoothStatusManager(
|
||||
activity = this,
|
||||
context = this,
|
||||
@@ -347,6 +349,12 @@ class MainActivity : OrientationAwareActivity() {
|
||||
bluetoothStatusManager.logBluetoothStatus()
|
||||
mainViewModel.updateBluetoothStatus(bluetoothStatusManager.checkBluetoothStatus())
|
||||
|
||||
val bleRequired = try { com.bitchat.android.ui.debug.DebugPreferenceManager.getBleEnabled(true) } catch (_: Exception) { true }
|
||||
if (!bleRequired) {
|
||||
// Skip BLE checks entirely when BLE is disabled in debug settings
|
||||
checkLocationAndProceed()
|
||||
return
|
||||
}
|
||||
when (mainViewModel.bluetoothStatus.value) {
|
||||
BluetoothStatus.ENABLED -> {
|
||||
// Bluetooth is enabled, check location services next
|
||||
@@ -513,8 +521,9 @@ class MainActivity : OrientationAwareActivity() {
|
||||
else -> BatteryOptimizationStatus.ENABLED
|
||||
}
|
||||
|
||||
val bleRequired2 = try { com.bitchat.android.ui.debug.DebugPreferenceManager.getBleEnabled(true) } catch (_: Exception) { true }
|
||||
when {
|
||||
currentBluetoothStatus != BluetoothStatus.ENABLED -> {
|
||||
bleRequired2 && currentBluetoothStatus != BluetoothStatus.ENABLED -> {
|
||||
// Bluetooth still disabled, but now we have permissions to enable it
|
||||
Log.d("MainActivity", "Permissions granted, but Bluetooth still disabled. Showing Bluetooth enable screen.")
|
||||
mainViewModel.updateBluetoothStatus(currentBluetoothStatus)
|
||||
|
||||
@@ -249,11 +249,16 @@ class BluetoothMeshService(private val context: Context) {
|
||||
override fun sendPacket(packet: BitchatPacket) {
|
||||
// Sign the packet before broadcasting
|
||||
val signedPacket = signPacketBeforeBroadcast(packet)
|
||||
connectionManager.broadcastPacket(RoutedPacket(signedPacket))
|
||||
val routed = RoutedPacket(signedPacket)
|
||||
connectionManager.broadcastPacket(routed)
|
||||
// Cross-transport relay to Wi‑Fi Aware if available
|
||||
try { com.bitchat.android.wifiaware.WifiAwareController.getService()?.broadcastRoutedPacket(routed) } catch (_: Exception) { }
|
||||
}
|
||||
|
||||
override fun relayPacket(routed: RoutedPacket) {
|
||||
connectionManager.broadcastPacket(routed)
|
||||
// Cross-transport relay to Wi‑Fi Aware if available
|
||||
try { com.bitchat.android.wifiaware.WifiAwareController.getService()?.broadcastRoutedPacket(routed) } catch (_: Exception) { }
|
||||
}
|
||||
|
||||
override fun getBroadcastRecipient(): ByteArray {
|
||||
|
||||
@@ -210,6 +210,7 @@ class MediaSendingManager(
|
||||
|
||||
Log.d(TAG, "📤 Calling meshService.sendFilePrivate to $toPeerID")
|
||||
meshService.sendFilePrivate(toPeerID, filePacket)
|
||||
try { com.bitchat.android.wifiaware.WifiAwareController.getService()?.sendFilePrivate(toPeerID, filePacket) } catch (_: Exception) {}
|
||||
Log.d(TAG, "✅ File send completed successfully")
|
||||
}
|
||||
|
||||
@@ -264,6 +265,7 @@ class MediaSendingManager(
|
||||
|
||||
Log.d(TAG, "📤 Calling meshService.sendFileBroadcast")
|
||||
meshService.sendFileBroadcast(filePacket)
|
||||
try { com.bitchat.android.wifiaware.WifiAwareController.getService()?.sendFileBroadcast(filePacket) } catch (_: Exception) {}
|
||||
Log.d(TAG, "✅ File broadcast completed successfully")
|
||||
}
|
||||
|
||||
|
||||
@@ -576,16 +576,21 @@ private fun PeerItem(
|
||||
tint = Color.Gray
|
||||
)
|
||||
} else {
|
||||
val wifiAwarePeers by com.bitchat.android.wifiaware.WifiAwareController.connectedPeers.collectAsState()
|
||||
val isWifiAware = wifiAwarePeers.containsKey(peerID)
|
||||
val awareConnected by com.bitchat.android.wifiaware.WifiAwareController.connectedPeers.collectAsState()
|
||||
val awareDiscovered by com.bitchat.android.wifiaware.WifiAwareController.discoveredPeers.collectAsState()
|
||||
val isWifiDirect = awareConnected.containsKey(peerID)
|
||||
val isBleDirect = isDirect
|
||||
val icon = when {
|
||||
isWifiAware -> Icons.Filled.Wifi
|
||||
isDirect -> Icons.Outlined.SettingsInputAntenna
|
||||
isWifiDirect -> Icons.Filled.Wifi
|
||||
isBleDirect -> Icons.Outlined.SettingsInputAntenna
|
||||
// Routed: show Route icon; optionally prefer Wi‑Fi Aware if discovered there
|
||||
awareDiscovered.contains(peerID) -> Icons.Filled.WifiTethering
|
||||
else -> Icons.Filled.Route
|
||||
}
|
||||
val cd = when {
|
||||
isWifiAware -> "Direct Wi‑Fi Aware"
|
||||
isDirect -> "Direct Bluetooth"
|
||||
isWifiDirect -> "Direct Wi‑Fi Aware"
|
||||
isBleDirect -> "Direct Bluetooth"
|
||||
awareDiscovered.contains(peerID) -> "Routed over Wi‑Fi"
|
||||
else -> "Routed"
|
||||
}
|
||||
Icon(
|
||||
|
||||
@@ -51,7 +51,7 @@ object WifiAwareController {
|
||||
try {
|
||||
val s = service
|
||||
if (s != null) {
|
||||
_connectedPeers.value = s.getDeviceAddressToPeerMapping().entries.associate { (ip, peer) -> peer to ip }
|
||||
_connectedPeers.value = s.getDeviceAddressToPeerMapping() // peerID -> ip
|
||||
_knownPeers.value = s.getPeerNicknames()
|
||||
_discoveredPeers.value = s.getDiscoveredPeerIds()
|
||||
} else {
|
||||
@@ -108,4 +108,9 @@ object WifiAwareController {
|
||||
}
|
||||
|
||||
fun getService(): WifiAwareMeshService? = service
|
||||
|
||||
// Optional bridge to BLE mesh for cross-transport relaying
|
||||
@Volatile private var bleMesh: com.bitchat.android.mesh.BluetoothMeshService? = null
|
||||
fun setBleMeshService(svc: com.bitchat.android.mesh.BluetoothMeshService) { bleMesh = svc }
|
||||
fun getBleMeshService(): com.bitchat.android.mesh.BluetoothMeshService? = bleMesh
|
||||
}
|
||||
|
||||
@@ -172,24 +172,39 @@ class WifiAwareMeshService(private val context: Context) {
|
||||
* Broadcasts routed packet to currently connected peers.
|
||||
*/
|
||||
private fun broadcastPacket(routed: RoutedPacket) {
|
||||
routed.packet.toBinaryData()?.let {
|
||||
routed.packet.toBinaryData()?.let { data ->
|
||||
Log.d(TAG, "TX: packet type=${routed.packet.type} broadcast (ttl=${routed.packet.ttl})")
|
||||
broadcastRaw(it)
|
||||
serviceScope.launch { broadcastRaw(data) }
|
||||
// Cross-transport relay (optional): also broadcast via BLE if available
|
||||
try { com.bitchat.android.wifiaware.WifiAwareController.getBleMeshService()?.connectionManager?.broadcastPacket(routed) } catch (_: Exception) { }
|
||||
}
|
||||
}
|
||||
|
||||
// Expose a public method so BLE can forward relays to Wi‑Fi Aware
|
||||
fun broadcastRoutedPacket(routed: RoutedPacket) {
|
||||
broadcastPacket(routed)
|
||||
}
|
||||
|
||||
/**
|
||||
* Send packet to connected peer.
|
||||
*/
|
||||
private fun sendPacketToPeer(peerID: String, packet: BitchatPacket) {
|
||||
val sock = peerSockets[peerID] ?: return
|
||||
try {
|
||||
val data = packet.toBinaryData() ?: return
|
||||
sock.getOutputStream().write(data)
|
||||
Log.d(TAG, "TX: packet type=${packet.type} → ${peerID.take(8)}… (bytes=${data.size})")
|
||||
} catch (e: IOException) {
|
||||
Log.e(TAG, "TX: write to ${peerID.take(8)}… failed: ${e.message}")
|
||||
val data = packet.toBinaryData() ?: return
|
||||
serviceScope.launch {
|
||||
val sock = peerSockets[peerID]
|
||||
if (sock == null) {
|
||||
Log.w(TAG, "TX: no socket for ${peerID.take(8)}…")
|
||||
return@launch
|
||||
}
|
||||
try {
|
||||
sock.getOutputStream().write(data)
|
||||
Log.d(TAG, "TX: packet type=${packet.type} → ${peerID.take(8)}… (bytes=${data.size})")
|
||||
} catch (e: IOException) {
|
||||
Log.e(TAG, "TX: write to ${peerID.take(8)}… failed: ${e.message}")
|
||||
}
|
||||
}
|
||||
// Cross-transport relay to BLE when unicast target is connected there too
|
||||
try { com.bitchat.android.wifiaware.WifiAwareController.getBleMeshService()?.connectionManager?.sendPacketToPeer(peerID, packet) } catch (_: Exception) { }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -279,17 +294,19 @@ class WifiAwareMeshService(private val context: Context) {
|
||||
override fun hasNoiseSession(peerID: String) =
|
||||
encryptionService.hasEstablishedSession(peerID)
|
||||
override fun initiateNoiseHandshake(peerID: String) {
|
||||
val hs = encryptionService.initiateHandshake(peerID) ?: return
|
||||
val packet = BitchatPacket(
|
||||
version = 1u,
|
||||
type = MessageType.NOISE_HANDSHAKE.value,
|
||||
senderID = hexStringToByteArray(myPeerID),
|
||||
recipientID = hexStringToByteArray(peerID),
|
||||
timestamp = System.currentTimeMillis().toULong(),
|
||||
payload = hs,
|
||||
ttl = MAX_TTL
|
||||
)
|
||||
broadcastPacket(RoutedPacket(signPacketBeforeBroadcast(packet)))
|
||||
serviceScope.launch {
|
||||
val hs = encryptionService.initiateHandshake(peerID) ?: return@launch
|
||||
val packet = BitchatPacket(
|
||||
version = 1u,
|
||||
type = MessageType.NOISE_HANDSHAKE.value,
|
||||
senderID = hexStringToByteArray(myPeerID),
|
||||
recipientID = hexStringToByteArray(peerID),
|
||||
timestamp = System.currentTimeMillis().toULong(),
|
||||
payload = hs,
|
||||
ttl = MAX_TTL
|
||||
)
|
||||
broadcastPacket(RoutedPacket(signPacketBeforeBroadcast(packet)))
|
||||
}
|
||||
}
|
||||
override fun processNoiseHandshakeMessage(payload: ByteArray, peerID: String): ByteArray? =
|
||||
try { encryptionService.processHandshakeMessage(payload, peerID) } catch (_: Exception) { null }
|
||||
@@ -593,8 +610,10 @@ class WifiAwareMeshService(private val context: Context) {
|
||||
// Kick off Noise handshake for this logical peer
|
||||
if (myPeerID < peerId) {
|
||||
messageHandler.delegate?.initiateNoiseHandshake(peerId)
|
||||
Log.d(TAG, "SERVER: initiating Noise handshake to ${peerId.take(8)}…")
|
||||
Log.d(TAG, "SERVER: initiating Noise handshake to ${peerId.take(8)}… (lower ID)")
|
||||
}
|
||||
// Ensure fast presence even before handshake settles
|
||||
serviceScope.launch { delay(150); sendBroadcastAnnounce() }
|
||||
} catch (ioe: IOException) {
|
||||
Log.e(TAG, "SERVER: accept failed for ${peerId.take(8)}…", ioe)
|
||||
}
|
||||
@@ -707,10 +726,12 @@ class WifiAwareMeshService(private val context: Context) {
|
||||
listenerExec.execute { listenToPeer(sock, peerId) }
|
||||
handleServerKeepAlive(sock, peerId, peerHandle)
|
||||
// Kick off Noise handshake for this logical peer
|
||||
if (myPeerID > peerId) {
|
||||
if (myPeerID < peerId) {
|
||||
messageHandler.delegate?.initiateNoiseHandshake(peerId)
|
||||
Log.d(TAG, "CLIENT: initiating Noise handshake to ${peerId.take(8)}…")
|
||||
Log.d(TAG, "CLIENT: initiating Noise handshake to ${peerId.take(8)}… (lower ID)")
|
||||
}
|
||||
// Ensure fast presence even before handshake settles
|
||||
serviceScope.launch { delay(150); sendBroadcastAnnounce() }
|
||||
} catch (ioe: IOException) {
|
||||
Log.e(TAG, "CLIENT: socket connect failed to ${peerId.take(8)}…", ioe)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user