mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 12:25:20 +00:00
fix review
This commit is contained in:
@@ -101,20 +101,9 @@ class BluetoothMeshService(private val context: Context) : TransportBridgeServic
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Wire sync manager delegate
|
com.bitchat.android.service.MeshServiceHolder.setGossipManager(gossipSyncManager) { packet ->
|
||||||
gossipSyncManager.delegate = object : GossipSyncManager.Delegate {
|
signPacketBeforeBroadcast(packet)
|
||||||
override fun sendPacket(packet: BitchatPacket) {
|
|
||||||
broadcastRoutedPacket(RoutedPacket(packet))
|
|
||||||
}
|
|
||||||
override fun sendPacketToPeer(peerID: String, packet: BitchatPacket) {
|
|
||||||
sendPacketToPeerAcrossTransports(peerID, packet)
|
|
||||||
}
|
|
||||||
override fun signPacketForBroadcast(packet: BitchatPacket): BitchatPacket {
|
|
||||||
return signPacketBeforeBroadcast(packet)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
com.bitchat.android.service.MeshServiceHolder.setGossipManager(gossipSyncManager)
|
|
||||||
if (isBleTransportEnabled()) {
|
if (isBleTransportEnabled()) {
|
||||||
TransportBridgeService.register("BLE", this)
|
TransportBridgeService.register("BLE", this)
|
||||||
}
|
}
|
||||||
@@ -144,13 +133,6 @@ class BluetoothMeshService(private val context: Context) : TransportBridgeServic
|
|||||||
TransportBridgeService.broadcast("BLE", routed)
|
TransportBridgeService.broadcast("BLE", routed)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sendPacketToPeerAcrossTransports(peerID: String, packet: BitchatPacket): Boolean {
|
|
||||||
if (!isBleTransportEnabled()) return false
|
|
||||||
val sentOverBle = connectionManager.sendPacketToPeer(peerID, packet)
|
|
||||||
TransportBridgeService.sendToPeer("BLE", peerID, packet)
|
|
||||||
return sentOverBle
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isBleTransportEnabled(): Boolean {
|
private fun isBleTransportEnabled(): Boolean {
|
||||||
return try {
|
return try {
|
||||||
com.bitchat.android.ui.debug.DebugSettingsManager.getInstance().bleEnabled.value
|
com.bitchat.android.ui.debug.DebugSettingsManager.getInstance().bleEnabled.value
|
||||||
@@ -670,8 +652,9 @@ class BluetoothMeshService(private val context: Context) : TransportBridgeServic
|
|||||||
Log.i(TAG, "BLE transport disabled by debug settings; not starting mesh service")
|
Log.i(TAG, "BLE transport disabled by debug settings; not starting mesh service")
|
||||||
connectionManager.disableTransport()
|
connectionManager.disableTransport()
|
||||||
TransportBridgeService.unregister("BLE")
|
TransportBridgeService.unregister("BLE")
|
||||||
|
com.bitchat.android.service.MeshServiceHolder.stopSharedGossip("BLE")
|
||||||
try { com.bitchat.android.services.AppStateStore.clearTransportPeers("BLE") } catch (_: Exception) { }
|
try { com.bitchat.android.services.AppStateStore.clearTransportPeers("BLE") } catch (_: Exception) { }
|
||||||
try { com.bitchat.android.services.AppStateStore.clearTransportDirectPeers("BLE") } catch (_: Exception) { }
|
try { com.bitchat.android.services.AppStateStore.clearTransportDirectPeers("BLE") } catch (_: Exception) { }
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (terminated) {
|
if (terminated) {
|
||||||
@@ -690,7 +673,7 @@ class BluetoothMeshService(private val context: Context) : TransportBridgeServic
|
|||||||
sendPeriodicBroadcastAnnounce()
|
sendPeriodicBroadcastAnnounce()
|
||||||
Log.d(TAG, "Started periodic broadcast announcements (every 30 seconds)")
|
Log.d(TAG, "Started periodic broadcast announcements (every 30 seconds)")
|
||||||
// Start periodic syncs
|
// Start periodic syncs
|
||||||
gossipSyncManager.start()
|
com.bitchat.android.service.MeshServiceHolder.startSharedGossip("BLE")
|
||||||
Log.d(TAG, "GossipSyncManager started")
|
Log.d(TAG, "GossipSyncManager started")
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "Failed to start Bluetooth services")
|
Log.e(TAG, "Failed to start Bluetooth services")
|
||||||
@@ -713,7 +696,7 @@ class BluetoothMeshService(private val context: Context) : TransportBridgeServic
|
|||||||
isActive = false
|
isActive = false
|
||||||
announceJob?.cancel()
|
announceJob?.cancel()
|
||||||
announceJob = null
|
announceJob = null
|
||||||
try { gossipSyncManager.stop() } catch (_: Exception) { }
|
com.bitchat.android.service.MeshServiceHolder.stopSharedGossip("BLE")
|
||||||
TransportBridgeService.unregister("BLE")
|
TransportBridgeService.unregister("BLE")
|
||||||
try { com.bitchat.android.services.AppStateStore.clearTransportPeers("BLE") } catch (_: Exception) { }
|
try { com.bitchat.android.services.AppStateStore.clearTransportPeers("BLE") } catch (_: Exception) { }
|
||||||
try { com.bitchat.android.services.AppStateStore.clearTransportDirectPeers("BLE") } catch (_: Exception) { }
|
try { com.bitchat.android.services.AppStateStore.clearTransportDirectPeers("BLE") } catch (_: Exception) { }
|
||||||
@@ -746,7 +729,7 @@ class BluetoothMeshService(private val context: Context) : TransportBridgeServic
|
|||||||
delay(200) // Give leave message time to send
|
delay(200) // Give leave message time to send
|
||||||
|
|
||||||
// Stop all components
|
// Stop all components
|
||||||
gossipSyncManager.stop()
|
com.bitchat.android.service.MeshServiceHolder.stopSharedGossip("BLE")
|
||||||
Log.d(TAG, "GossipSyncManager stopped")
|
Log.d(TAG, "GossipSyncManager stopped")
|
||||||
connectionManager.stopServices()
|
connectionManager.stopServices()
|
||||||
Log.d(TAG, "BluetoothConnectionManager stop requested")
|
Log.d(TAG, "BluetoothConnectionManager stop requested")
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ package com.bitchat.android.service
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.bitchat.android.mesh.BluetoothMeshService
|
import com.bitchat.android.mesh.BluetoothMeshService
|
||||||
import com.bitchat.android.mesh.UnifiedMeshService
|
import com.bitchat.android.mesh.UnifiedMeshService
|
||||||
|
import com.bitchat.android.model.RoutedPacket
|
||||||
|
import com.bitchat.android.protocol.BitchatPacket
|
||||||
|
import com.bitchat.android.sync.GossipSyncManager
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process-wide holder to share a single BluetoothMeshService instance
|
* Process-wide holder to share a single BluetoothMeshService instance
|
||||||
@@ -11,10 +14,59 @@ import com.bitchat.android.mesh.UnifiedMeshService
|
|||||||
object MeshServiceHolder {
|
object MeshServiceHolder {
|
||||||
private const val TAG = "MeshServiceHolder"
|
private const val TAG = "MeshServiceHolder"
|
||||||
@Volatile
|
@Volatile
|
||||||
var sharedGossipSyncManager: com.bitchat.android.sync.GossipSyncManager? = null
|
var sharedGossipSyncManager: GossipSyncManager? = null
|
||||||
private set
|
private set
|
||||||
|
|
||||||
fun setGossipManager(mgr: com.bitchat.android.sync.GossipSyncManager) { sharedGossipSyncManager = mgr }
|
private val activeGossipOwners = mutableSetOf<String>()
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
fun setGossipManager(
|
||||||
|
mgr: GossipSyncManager,
|
||||||
|
signer: (BitchatPacket) -> BitchatPacket
|
||||||
|
) {
|
||||||
|
val previous = sharedGossipSyncManager
|
||||||
|
if (previous !== mgr) {
|
||||||
|
try { previous?.stop() } catch (_: Exception) { }
|
||||||
|
}
|
||||||
|
sharedGossipSyncManager = mgr
|
||||||
|
mgr.delegate = TransportGossipDelegate(signer)
|
||||||
|
if (activeGossipOwners.isNotEmpty()) {
|
||||||
|
mgr.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
fun startSharedGossip(owner: String) {
|
||||||
|
val wasIdle = activeGossipOwners.isEmpty()
|
||||||
|
activeGossipOwners.add(owner)
|
||||||
|
if (wasIdle) {
|
||||||
|
sharedGossipSyncManager?.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
fun stopSharedGossip(owner: String) {
|
||||||
|
activeGossipOwners.remove(owner)
|
||||||
|
if (activeGossipOwners.isEmpty()) {
|
||||||
|
sharedGossipSyncManager?.stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TransportGossipDelegate(
|
||||||
|
private val signer: (BitchatPacket) -> BitchatPacket
|
||||||
|
) : GossipSyncManager.Delegate {
|
||||||
|
override fun sendPacket(packet: BitchatPacket) {
|
||||||
|
TransportBridgeService.broadcastFromLocal(RoutedPacket(packet))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun sendPacketToPeer(peerID: String, packet: BitchatPacket) {
|
||||||
|
TransportBridgeService.sendToPeerFromLocal(peerID, packet)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun signPacketForBroadcast(packet: BitchatPacket): BitchatPacket {
|
||||||
|
return signer(packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
var meshService: BluetoothMeshService? = null
|
var meshService: BluetoothMeshService? = null
|
||||||
@@ -84,6 +136,9 @@ object MeshServiceHolder {
|
|||||||
@Synchronized
|
@Synchronized
|
||||||
fun clear() {
|
fun clear() {
|
||||||
android.util.Log.d(TAG, "Clearing BluetoothMeshService from holder")
|
android.util.Log.d(TAG, "Clearing BluetoothMeshService from holder")
|
||||||
|
try { sharedGossipSyncManager?.stop() } catch (_: Exception) { }
|
||||||
|
sharedGossipSyncManager = null
|
||||||
|
activeGossipOwners.clear()
|
||||||
meshService = null
|
meshService = null
|
||||||
unifiedMeshService = null
|
unifiedMeshService = null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,6 +105,40 @@ object TransportBridgeService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a locally originated packet to every active transport without applying relay TTL
|
||||||
|
* handling. This is used for neighbor-only packets such as REQUEST_SYNC whose TTL is
|
||||||
|
* intentionally zero on the first radio hop.
|
||||||
|
*/
|
||||||
|
fun broadcastFromLocal(packet: RoutedPacket) {
|
||||||
|
val targets = transports.toMap()
|
||||||
|
if (targets.isEmpty()) return
|
||||||
|
|
||||||
|
targets.forEach { (id, layer) ->
|
||||||
|
try {
|
||||||
|
layer.send(packet)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Failed to send local packet to $id: ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a locally originated packet directly to a peer on every active transport.
|
||||||
|
*/
|
||||||
|
fun sendToPeerFromLocal(peerID: String, packet: BitchatPacket) {
|
||||||
|
val targets = transports.toMap()
|
||||||
|
if (targets.isEmpty()) return
|
||||||
|
|
||||||
|
targets.forEach { (id, layer) ->
|
||||||
|
try {
|
||||||
|
layer.sendToPeer(peerID, packet)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Failed to send local peer packet to $id: ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun prepareForwardedPacket(kind: String, packet: BitchatPacket): BitchatPacket? {
|
private fun prepareForwardedPacket(kind: String, packet: BitchatPacket): BitchatPacket? {
|
||||||
if (packet.ttl == 0u.toUByte()) {
|
if (packet.ttl == 0u.toUByte()) {
|
||||||
Log.d(TAG, "Dropping bridged packet type ${packet.type}: TTL expired")
|
Log.d(TAG, "Dropping bridged packet type ${packet.type}: TTL expired")
|
||||||
|
|||||||
@@ -492,12 +492,13 @@ class WifiAwareMeshService(private val context: Context) : MeshService, Transpor
|
|||||||
}
|
}
|
||||||
}, Handler(Looper.getMainLooper()))
|
}, Handler(Looper.getMainLooper()))
|
||||||
|
|
||||||
meshCore.startCore()
|
|
||||||
startPeriodicConnectionMaintenance()
|
|
||||||
connectionTracker.start()
|
|
||||||
|
|
||||||
// Register with cross-layer transport bridge
|
// Register with cross-layer transport bridge
|
||||||
TransportBridgeService.register("WIFI", this)
|
TransportBridgeService.register("WIFI", this)
|
||||||
|
|
||||||
|
meshCore.startCore()
|
||||||
|
com.bitchat.android.service.MeshServiceHolder.startSharedGossip("WIFI")
|
||||||
|
startPeriodicConnectionMaintenance()
|
||||||
|
connectionTracker.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -511,6 +512,7 @@ class WifiAwareMeshService(private val context: Context) : MeshService, Transpor
|
|||||||
|
|
||||||
// Unregister from bridge
|
// Unregister from bridge
|
||||||
TransportBridgeService.unregister("WIFI")
|
TransportBridgeService.unregister("WIFI")
|
||||||
|
com.bitchat.android.service.MeshServiceHolder.stopSharedGossip("WIFI")
|
||||||
try { com.bitchat.android.services.AppStateStore.clearTransportPeers("WIFI") } catch (_: Exception) { }
|
try { com.bitchat.android.services.AppStateStore.clearTransportPeers("WIFI") } catch (_: Exception) { }
|
||||||
try { com.bitchat.android.services.AppStateStore.clearTransportDirectPeers("WIFI") } catch (_: Exception) { }
|
try { com.bitchat.android.services.AppStateStore.clearTransportDirectPeers("WIFI") } catch (_: Exception) { }
|
||||||
|
|
||||||
@@ -554,6 +556,7 @@ class WifiAwareMeshService(private val context: Context) : MeshService, Transpor
|
|||||||
recoveryInProgress = true
|
recoveryInProgress = true
|
||||||
isActive = false
|
isActive = false
|
||||||
TransportBridgeService.unregister("WIFI")
|
TransportBridgeService.unregister("WIFI")
|
||||||
|
com.bitchat.android.service.MeshServiceHolder.stopSharedGossip("WIFI")
|
||||||
try { com.bitchat.android.services.AppStateStore.clearTransportPeers("WIFI") } catch (_: Exception) { }
|
try { com.bitchat.android.services.AppStateStore.clearTransportPeers("WIFI") } catch (_: Exception) { }
|
||||||
try { com.bitchat.android.services.AppStateStore.clearTransportDirectPeers("WIFI") } catch (_: Exception) { }
|
try { com.bitchat.android.services.AppStateStore.clearTransportDirectPeers("WIFI") } catch (_: Exception) { }
|
||||||
val oldPublishSession = publishSession
|
val oldPublishSession = publishSession
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package com.bitchat.android.ui
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.test.core.app.ApplicationProvider
|
import androidx.test.core.app.ApplicationProvider
|
||||||
import com.bitchat.android.mesh.BluetoothMeshService
|
import com.bitchat.android.mesh.MeshService
|
||||||
import com.bitchat.android.model.BitchatMessage
|
import com.bitchat.android.model.BitchatMessage
|
||||||
import junit.framework.TestCase.assertEquals
|
import junit.framework.TestCase.assertEquals
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
@@ -34,7 +34,7 @@ class CommandProcessorTest() {
|
|||||||
coroutineScope = testScope
|
coroutineScope = testScope
|
||||||
)
|
)
|
||||||
|
|
||||||
private val meshService: BluetoothMeshService = mock()
|
private val meshService: MeshService = mock()
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
|
|||||||
Reference in New Issue
Block a user