mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 12:25:20 +00:00
Implement Noise XX Handshake Protocol for Direct Messages (#180)
* noise * works? * noise * temporary * better * wip: use subnet * better * barely working * werk * subnet * fix peer ID * 8 byte peer ID * wip noise * wip fixes for noise * std lib for noise * noise handshake one step further * buffers * use fork * fix imports * simplify counter * remove trash * hashing * no prologue * nice * wip, use noise encryption * peer ID hex * simplify session manager * heavy logging * use singleton * Fix Noise session race condition with elegant per-peer actor serialization - Use Kotlin coroutine actors for per-peer packet processing - Each peer gets dedicated actor that processes packets sequentially - Eliminates race conditions in session management without complex locking - Single surgical change in PacketProcessor - minimal, maintainable - Leverages Kotlin's native concurrency primitives * decrypt correctly * iniator works now * clean code and fix signature to null * better * no signature in private message * small fixes * refactor ack * refactor but untested * messages working * wip ack * wip fix ack * more logging * pending tracker * keep pending connections on errors * less logging * refactor model * refactor frombinarydata * idendityannouncement refactor and update to new binary protocol * fix keys * refix keys * dms work * revert to mainnet * do not change bluetooth adapter name * keep code but uncomment * clean up comments * cleanup comments
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
package com.bitchat.android.protocol
|
||||
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.util.zip.Deflater
|
||||
import java.util.zip.Inflater
|
||||
|
||||
/**
|
||||
* Compression utilities - LZ4-like functionality using Deflater/Inflater
|
||||
* Android doesn't have native LZ4, so we use Java's built-in compression
|
||||
*/
|
||||
object CompressionUtil {
|
||||
private const val COMPRESSION_THRESHOLD = 100 // bytes - same as iOS
|
||||
|
||||
/**
|
||||
* Helper to check if compression is worth it - exact same logic as iOS
|
||||
*/
|
||||
fun shouldCompress(data: ByteArray): Boolean {
|
||||
// Don't compress if:
|
||||
// 1. Data is too small
|
||||
// 2. Data appears to be already compressed (high entropy)
|
||||
if (data.size < COMPRESSION_THRESHOLD) return false
|
||||
|
||||
// Simple entropy check - count unique bytes
|
||||
val byteFrequency = mutableMapOf<Byte, Int>()
|
||||
for (byte in data) {
|
||||
byteFrequency[byte] = (byteFrequency[byte] ?: 0) + 1
|
||||
}
|
||||
|
||||
// If we have very high byte diversity, data is likely already compressed
|
||||
val uniqueByteRatio = byteFrequency.size.toDouble() / minOf(data.size, 256).toDouble()
|
||||
return uniqueByteRatio < 0.9 // Compress if less than 90% unique bytes
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress data using Deflater (closest to LZ4 available on Android)
|
||||
*/
|
||||
fun compress(data: ByteArray): ByteArray? {
|
||||
// Skip compression for small data
|
||||
if (data.size < COMPRESSION_THRESHOLD) return null
|
||||
|
||||
try {
|
||||
val deflater = Deflater(Deflater.BEST_SPEED) // Fast compression like LZ4
|
||||
deflater.setInput(data)
|
||||
deflater.finish()
|
||||
|
||||
val buffer = ByteArray(data.size + 16) // Some overhead space
|
||||
val compressedSize = deflater.deflate(buffer)
|
||||
deflater.end()
|
||||
|
||||
// Only return if compression was beneficial
|
||||
if (compressedSize > 0 && compressedSize < data.size) {
|
||||
return buffer.copyOfRange(0, compressedSize)
|
||||
}
|
||||
|
||||
return null
|
||||
} catch (e: Exception) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompress data using Inflater
|
||||
*/
|
||||
fun decompress(compressedData: ByteArray, originalSize: Int): ByteArray? {
|
||||
try {
|
||||
val inflater = Inflater()
|
||||
inflater.setInput(compressedData)
|
||||
|
||||
val result = ByteArray(originalSize)
|
||||
val decompressedSize = inflater.inflate(result)
|
||||
inflater.end()
|
||||
|
||||
if (decompressedSize > 0) {
|
||||
return if (decompressedSize == originalSize) {
|
||||
result
|
||||
} else {
|
||||
result.copyOfRange(0, decompressedSize)
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
} catch (e: Exception) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user