mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 05:05:20 +00:00
no signature in private message
This commit is contained in:
@@ -64,7 +64,7 @@ class BluetoothMeshService(private val context: Context) {
|
|||||||
|
|
||||||
// Wire up PacketProcessor reference for recursive handling in MessageHandler
|
// Wire up PacketProcessor reference for recursive handling in MessageHandler
|
||||||
messageHandler.packetProcessor = packetProcessor
|
messageHandler.packetProcessor = packetProcessor
|
||||||
// startPeriodicDebugLogging()
|
startPeriodicDebugLogging()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -491,7 +491,7 @@ class BluetoothMeshService(private val context: Context) {
|
|||||||
|
|
||||||
if (encryptedPayload != null) {
|
if (encryptedPayload != null) {
|
||||||
// Sign
|
// Sign
|
||||||
val signature = securityManager.signPacket(encryptedPayload)
|
// val signature = securityManager.signPacket(encryptedPayload)
|
||||||
|
|
||||||
val packet = BitchatPacket(
|
val packet = BitchatPacket(
|
||||||
version = 1u,
|
version = 1u,
|
||||||
@@ -500,7 +500,7 @@ class BluetoothMeshService(private val context: Context) {
|
|||||||
recipientID = hexStringToByteArray(recipientPeerID),
|
recipientID = hexStringToByteArray(recipientPeerID),
|
||||||
timestamp = System.currentTimeMillis().toULong(),
|
timestamp = System.currentTimeMillis().toULong(),
|
||||||
payload = encryptedPayload,
|
payload = encryptedPayload,
|
||||||
signature = signature,
|
signature = null,
|
||||||
ttl = MAX_TTL
|
ttl = MAX_TTL
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -8,11 +8,20 @@ import android.util.Log
|
|||||||
import com.bitchat.android.protocol.SpecialRecipients
|
import com.bitchat.android.protocol.SpecialRecipients
|
||||||
import com.bitchat.android.model.RoutedPacket
|
import com.bitchat.android.model.RoutedPacket
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import kotlinx.coroutines.cancel
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.isActive
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.channels.Channel
|
||||||
|
import kotlinx.coroutines.channels.actor
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles packet broadcasting to connected devices
|
* Handles packet broadcasting to connected devices using actor pattern for serialization
|
||||||
|
*
|
||||||
|
* SERIALIZATION FIX: Uses Kotlin coroutine actor to serialize all packet broadcasting
|
||||||
|
* This prevents race conditions when multiple threads try to broadcast simultaneously
|
||||||
*/
|
*/
|
||||||
class BluetoothPacketBroadcaster(
|
class BluetoothPacketBroadcaster(
|
||||||
private val connectionScope: CoroutineScope,
|
private val connectionScope: CoroutineScope,
|
||||||
@@ -25,6 +34,33 @@ class BluetoothPacketBroadcaster(
|
|||||||
private const val CLEANUP_DELAY = 500L
|
private const val CLEANUP_DELAY = 500L
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Data class to hold broadcast request information
|
||||||
|
private data class BroadcastRequest(
|
||||||
|
val routed: RoutedPacket,
|
||||||
|
val gattServer: BluetoothGattServer?,
|
||||||
|
val characteristic: BluetoothGattCharacteristic?
|
||||||
|
)
|
||||||
|
|
||||||
|
// Actor scope for the broadcaster
|
||||||
|
private val broadcasterScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
|
||||||
|
|
||||||
|
// SERIALIZATION: Actor to serialize all broadcast operations
|
||||||
|
@OptIn(kotlinx.coroutines.ObsoleteCoroutinesApi::class)
|
||||||
|
private val broadcasterActor = broadcasterScope.actor<BroadcastRequest>(
|
||||||
|
capacity = Channel.UNLIMITED
|
||||||
|
) {
|
||||||
|
Log.d(TAG, "🎭 Created packet broadcaster actor")
|
||||||
|
try {
|
||||||
|
for (request in channel) {
|
||||||
|
Log.d(TAG, "Processing broadcast for packet type ${request.routed.packet.type} (serialized)")
|
||||||
|
broadcastSinglePacketInternal(request.routed, request.gattServer, request.characteristic)
|
||||||
|
Log.d(TAG, "Completed broadcast for packet type ${request.routed.packet.type}")
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
Log.d(TAG, "🎭 Packet broadcaster actor terminated")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun broadcastPacket(
|
fun broadcastPacket(
|
||||||
routed: RoutedPacket,
|
routed: RoutedPacket,
|
||||||
gattServer: BluetoothGattServer?,
|
gattServer: BluetoothGattServer?,
|
||||||
@@ -54,12 +90,32 @@ class BluetoothPacketBroadcaster(
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Broadcast single packet to connected devices with connection limit enforcement
|
* Public entry point for broadcasting - submits request to actor for serialization
|
||||||
*/
|
*/
|
||||||
fun broadcastSinglePacket(
|
fun broadcastSinglePacket(
|
||||||
routed: RoutedPacket,
|
routed: RoutedPacket,
|
||||||
gattServer: BluetoothGattServer?,
|
gattServer: BluetoothGattServer?,
|
||||||
characteristic: BluetoothGattCharacteristic?
|
characteristic: BluetoothGattCharacteristic?
|
||||||
|
) {
|
||||||
|
// Submit broadcast request to actor for serialized processing
|
||||||
|
broadcasterScope.launch {
|
||||||
|
try {
|
||||||
|
broadcasterActor.send(BroadcastRequest(routed, gattServer, characteristic))
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.w(TAG, "Failed to send broadcast request to actor: ${e.message}")
|
||||||
|
// Fallback to direct processing if actor fails
|
||||||
|
broadcastSinglePacketInternal(routed, gattServer, characteristic)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal broadcast implementation - runs in serialized actor context
|
||||||
|
*/
|
||||||
|
private suspend fun broadcastSinglePacketInternal(
|
||||||
|
routed: RoutedPacket,
|
||||||
|
gattServer: BluetoothGattServer?,
|
||||||
|
characteristic: BluetoothGattCharacteristic?
|
||||||
) {
|
) {
|
||||||
val packet = routed.packet
|
val packet = routed.packet
|
||||||
val data = packet.toBinaryData() ?: return
|
val data = packet.toBinaryData() ?: return
|
||||||
@@ -177,4 +233,31 @@ class BluetoothPacketBroadcaster(
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get debug information
|
||||||
|
*/
|
||||||
|
fun getDebugInfo(): String {
|
||||||
|
return buildString {
|
||||||
|
appendLine("=== Packet Broadcaster Debug Info ===")
|
||||||
|
appendLine("Broadcaster Scope Active: ${broadcasterScope.isActive}")
|
||||||
|
appendLine("Actor Channel Closed: ${broadcasterActor.isClosedForSend}")
|
||||||
|
appendLine("Connection Scope Active: ${connectionScope.isActive}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shutdown the broadcaster actor gracefully
|
||||||
|
*/
|
||||||
|
fun shutdown() {
|
||||||
|
Log.d(TAG, "Shutting down BluetoothPacketBroadcaster actor")
|
||||||
|
|
||||||
|
// Close the actor gracefully
|
||||||
|
broadcasterActor.close()
|
||||||
|
|
||||||
|
// Cancel the broadcaster scope
|
||||||
|
broadcasterScope.cancel()
|
||||||
|
|
||||||
|
Log.d(TAG, "BluetoothPacketBroadcaster shutdown complete")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -14,6 +14,7 @@ class FragmentManager {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "FragmentManager"
|
private const val TAG = "FragmentManager"
|
||||||
|
private const val FRAGMENT_SIZE_THRESHOLD = 512 // 512 bytes
|
||||||
private const val MAX_FRAGMENT_SIZE = 500 // Match iOS/Rust for BLE compatibility (185 byte MTU limit)
|
private const val MAX_FRAGMENT_SIZE = 500 // Match iOS/Rust for BLE compatibility (185 byte MTU limit)
|
||||||
private const val FRAGMENT_TIMEOUT = 30000L // 30 seconds
|
private const val FRAGMENT_TIMEOUT = 30000L // 30 seconds
|
||||||
private const val CLEANUP_INTERVAL = 10000L // 10 seconds
|
private const val CLEANUP_INTERVAL = 10000L // 10 seconds
|
||||||
@@ -39,7 +40,7 @@ class FragmentManager {
|
|||||||
fun createFragments(packet: BitchatPacket): List<BitchatPacket> {
|
fun createFragments(packet: BitchatPacket): List<BitchatPacket> {
|
||||||
val data = packet.toBinaryData() ?: return emptyList()
|
val data = packet.toBinaryData() ?: return emptyList()
|
||||||
|
|
||||||
if (data.size <= MAX_FRAGMENT_SIZE) {
|
if (data.size <= FRAGMENT_SIZE_THRESHOLD) {
|
||||||
return listOf(packet) // No fragmentation needed
|
return listOf(packet) // No fragmentation needed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user