mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 20:05:21 +00:00
fix: sync own messages
This commit is contained in:
@@ -51,7 +51,14 @@ class BluetoothConnectionManager(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (peerID == myPeerID) return // Ignore messages from self
|
// Normally ignore messages from self, but accept local-only sync responses (TTL=0)
|
||||||
|
if (peerID == myPeerID) {
|
||||||
|
if (packet.ttl == 0u.toUByte()) {
|
||||||
|
Log.d(TAG, "Accepting self-sender packet with TTL=0 (likely SYNC response)")
|
||||||
|
} else {
|
||||||
|
return // Ignore non-sync self packets
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
delegate?.onPacketReceived(packet, peerID, device)
|
delegate?.onPacketReceived(packet, peerID, device)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ class MessageHandler(private val myPeerID: String) {
|
|||||||
val packet = routed.packet
|
val packet = routed.packet
|
||||||
val peerID = routed.peerID ?: "unknown"
|
val peerID = routed.peerID ?: "unknown"
|
||||||
|
|
||||||
if (peerID == myPeerID) return false
|
if (peerID == myPeerID && routed.packet.ttl != 0u.toUByte()) return false
|
||||||
|
|
||||||
// Try to decode as iOS-compatible IdentityAnnouncement with TLV format
|
// Try to decode as iOS-compatible IdentityAnnouncement with TLV format
|
||||||
val announcement = IdentityAnnouncement.decode(packet.payload)
|
val announcement = IdentityAnnouncement.decode(packet.payload)
|
||||||
@@ -304,7 +304,8 @@ class MessageHandler(private val myPeerID: String) {
|
|||||||
suspend fun handleMessage(routed: RoutedPacket) {
|
suspend fun handleMessage(routed: RoutedPacket) {
|
||||||
val packet = routed.packet
|
val packet = routed.packet
|
||||||
val peerID = routed.peerID ?: "unknown"
|
val peerID = routed.peerID ?: "unknown"
|
||||||
if (peerID == myPeerID) return
|
// IMPORTANT: Allow TTL=0 self packets (sync responses) to flow through
|
||||||
|
if (peerID == myPeerID && packet.ttl != 0u.toUByte()) return
|
||||||
val senderNickname = delegate?.getPeerNickname(peerID)
|
val senderNickname = delegate?.getPeerNickname(peerID)
|
||||||
if (senderNickname != null) {
|
if (senderNickname != null) {
|
||||||
Log.d(TAG, "Received message from $senderNickname")
|
Log.d(TAG, "Received message from $senderNickname")
|
||||||
@@ -331,8 +332,9 @@ class MessageHandler(private val myPeerID: String) {
|
|||||||
val peerID = routed.peerID ?: "unknown"
|
val peerID = routed.peerID ?: "unknown"
|
||||||
|
|
||||||
// Enforce: only accept public messages from verified peers we know
|
// Enforce: only accept public messages from verified peers we know
|
||||||
|
// EXCEPTION: allow our own messages (peerID == myPeerID), e.g. TTL=0 sync responses
|
||||||
val peerInfo = delegate?.getPeerInfo(peerID)
|
val peerInfo = delegate?.getPeerInfo(peerID)
|
||||||
if (peerInfo == null || !peerInfo.isVerifiedNickname) {
|
if (peerID != myPeerID && (peerInfo == null || !peerInfo.isVerifiedNickname)) {
|
||||||
Log.w(TAG, "🚫 Dropping public message from unverified or unknown peer ${peerID.take(8)}...")
|
Log.w(TAG, "🚫 Dropping public message from unverified or unknown peer ${peerID.take(8)}...")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -340,7 +342,7 @@ class MessageHandler(private val myPeerID: String) {
|
|||||||
try {
|
try {
|
||||||
// Parse message
|
// Parse message
|
||||||
val message = BitchatMessage(
|
val message = BitchatMessage(
|
||||||
sender = delegate?.getPeerNickname(peerID) ?: "unknown",
|
sender = if (peerID == myPeerID) (delegate?.getMyNickname() ?: myPeerID) else (delegate?.getPeerNickname(peerID) ?: "unknown"),
|
||||||
content = String(packet.payload, Charsets.UTF_8),
|
content = String(packet.payload, Charsets.UTF_8),
|
||||||
senderPeerID = peerID,
|
senderPeerID = peerID,
|
||||||
timestamp = Date(packet.timestamp.toLong())
|
timestamp = Date(packet.timestamp.toLong())
|
||||||
|
|||||||
@@ -44,11 +44,17 @@ class SecurityManager(private val encryptionService: EncryptionService, private
|
|||||||
* Validate packet security (timestamp, replay attacks, duplicates, signatures)
|
* Validate packet security (timestamp, replay attacks, duplicates, signatures)
|
||||||
*/
|
*/
|
||||||
fun validatePacket(packet: BitchatPacket, peerID: String): Boolean {
|
fun validatePacket(packet: BitchatPacket, peerID: String): Boolean {
|
||||||
// Skip validation for our own packets
|
// Allow our own packets only when they are local-only (TTL=0) — used by SYNC responses
|
||||||
if (peerID == myPeerID) {
|
if (peerID == myPeerID) {
|
||||||
Log.d(TAG, "Skipping validation for our own packet")
|
val isLocalOnly = packet.ttl == 0u.toUByte()
|
||||||
|
if (isLocalOnly) {
|
||||||
|
Log.d(TAG, "Accepting self packet due to TTL=0 (SYNC/local-only)")
|
||||||
|
// Intentionally continue to duplicate detection to avoid showing duplicates
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "Dropping non-local self packet during validation")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Validate packet payload
|
// Validate packet payload
|
||||||
if (packet.payload.isEmpty()) {
|
if (packet.payload.isEmpty()) {
|
||||||
|
|||||||
@@ -156,8 +156,12 @@ class GossipSyncManager(
|
|||||||
return GCSFilter.contains(sorted, v)
|
return GCSFilter.contains(sorted, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Track what we send per original sender peerID (hex)
|
||||||
|
data class SentStats(var announce: Boolean = false, var msgCount: Int = 0)
|
||||||
|
val sentBySender = mutableMapOf<String, SentStats>()
|
||||||
|
|
||||||
// 1) Announcements: send latest per peerID if remote doesn't have them
|
// 1) Announcements: send latest per peerID if remote doesn't have them
|
||||||
for ((_, pair) in latestAnnouncementByPeer.entries) {
|
for ((senderHex, pair) in latestAnnouncementByPeer.entries) {
|
||||||
val (id, pkt) = pair
|
val (id, pkt) = pair
|
||||||
val idBytes = hexToBytes(id)
|
val idBytes = hexToBytes(id)
|
||||||
if (!mightContain(idBytes)) {
|
if (!mightContain(idBytes)) {
|
||||||
@@ -165,6 +169,7 @@ class GossipSyncManager(
|
|||||||
val toSend = pkt.copy(ttl = 0u)
|
val toSend = pkt.copy(ttl = 0u)
|
||||||
delegate?.sendPacketToPeer(fromPeerID, toSend)
|
delegate?.sendPacketToPeer(fromPeerID, toSend)
|
||||||
Log.d(TAG, "Sent sync announce: Type ${toSend.type} from ${toSend.senderID.toHexString()} to $fromPeerID packet id ${idBytes.toHexString()}")
|
Log.d(TAG, "Sent sync announce: Type ${toSend.type} from ${toSend.senderID.toHexString()} to $fromPeerID packet id ${idBytes.toHexString()}")
|
||||||
|
sentBySender.getOrPut(senderHex) { SentStats() }.apply { announce = true }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,6 +181,17 @@ class GossipSyncManager(
|
|||||||
val toSend = pkt.copy(ttl = 0u)
|
val toSend = pkt.copy(ttl = 0u)
|
||||||
delegate?.sendPacketToPeer(fromPeerID, toSend)
|
delegate?.sendPacketToPeer(fromPeerID, toSend)
|
||||||
Log.d(TAG, "Sent sync message: Type ${toSend.type} to $fromPeerID packet id ${idBytes.toHexString()}")
|
Log.d(TAG, "Sent sync message: Type ${toSend.type} to $fromPeerID packet id ${idBytes.toHexString()}")
|
||||||
|
val senderHex = pkt.senderID.joinToString("") { b -> "%02x".format(b) }
|
||||||
|
sentBySender.getOrPut(senderHex) { SentStats() }.apply { msgCount += 1 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Summary log per sender (original packet senderID)
|
||||||
|
if (sentBySender.isEmpty()) {
|
||||||
|
Log.d(TAG, "SYNC_RESPONSE summary to $fromPeerID: nothing to send")
|
||||||
|
} else {
|
||||||
|
for ((senderHex, stats) in sentBySender) {
|
||||||
|
Log.d(TAG, "SYNC_RESPONSE summary to $fromPeerID for sender $senderHex: announce=${stats.announce}, messages=${stats.msgCount}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user