mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 11:05:20 +00:00
Init handshake on dm (#187)
* kinda working * establish handshake if not done yet * add handshakerequest packet * read receipt
This commit is contained in:
@@ -5,6 +5,7 @@ import android.util.Log
|
||||
import com.bitchat.android.crypto.EncryptionService
|
||||
import com.bitchat.android.protocol.MessagePadding
|
||||
import com.bitchat.android.model.BitchatMessage
|
||||
import com.bitchat.android.model.HandshakeRequest
|
||||
import com.bitchat.android.model.RoutedPacket
|
||||
import com.bitchat.android.model.DeliveryAck
|
||||
import com.bitchat.android.model.ReadReceipt
|
||||
@@ -556,7 +557,6 @@ class BluetoothMeshService(private val context: Context) {
|
||||
)
|
||||
|
||||
try {
|
||||
// TODO: THIS FORMAT FOR DELIVERY ACKS SHOULD BE DEPRECATED
|
||||
val ackData = ack.encode() ?: return
|
||||
val typeMarker = MessageType.DELIVERY_ACK.value.toByte()
|
||||
val payloadWithMarker = byteArrayOf(typeMarker) + ackData
|
||||
@@ -591,36 +591,41 @@ class BluetoothMeshService(private val context: Context) {
|
||||
*/
|
||||
fun sendReadReceipt(messageID: String, recipientPeerID: String, readerNickname: String) {
|
||||
serviceScope.launch {
|
||||
// Create the read receipt
|
||||
val receipt = ReadReceipt(
|
||||
originalMessageID = messageID,
|
||||
readerID = myPeerID,
|
||||
readerNickname = readerNickname
|
||||
)
|
||||
|
||||
try {
|
||||
Log.d(TAG, "Sending read receipt for message $messageID to $recipientPeerID")
|
||||
|
||||
// Create the read receipt
|
||||
val receipt = ReadReceipt(
|
||||
originalMessageID = messageID,
|
||||
readerID = myPeerID,
|
||||
readerNickname = readerNickname
|
||||
)
|
||||
|
||||
// Encode the receipt
|
||||
val receiptData = receipt.encode()
|
||||
|
||||
// Create inner read receipt packet
|
||||
val innerPacket = BitchatPacket(
|
||||
version = 1u,
|
||||
type = MessageType.READ_RECEIPT.value,
|
||||
val typeMarker = MessageType.READ_RECEIPT.value.toByte()
|
||||
val payloadWithMarker = byteArrayOf(typeMarker) + receiptData
|
||||
val encryptedPayload = securityManager.encryptForPeer(payloadWithMarker, recipientPeerID)
|
||||
|
||||
if (encryptedPayload == null) {
|
||||
Log.w(TAG, "Failed to encrypt delivery ACK for $recipientPeerID")
|
||||
return@launch
|
||||
}
|
||||
|
||||
// Create inner packet with the delivery ACK data
|
||||
val packet = BitchatPacket(
|
||||
type = MessageType.NOISE_ENCRYPTED.value,
|
||||
senderID = hexStringToByteArray(myPeerID),
|
||||
recipientID = hexStringToByteArray(recipientPeerID),
|
||||
timestamp = System.currentTimeMillis().toULong(),
|
||||
payload = receiptData,
|
||||
payload = encryptedPayload,
|
||||
signature = null,
|
||||
ttl = 3u
|
||||
)
|
||||
|
||||
// Encrypt the entire inner packet and send as NOISE_ENCRYPTED
|
||||
encryptAndBroadcastNoisePacket(innerPacket, recipientPeerID)
|
||||
|
||||
Log.d(TAG, "Sent read receipt for message $messageID to $recipientPeerID")
|
||||
|
||||
|
||||
Log.d(TAG, "Sending read receipt for message $messageID to $recipientPeerID")
|
||||
|
||||
// Use the new encrypt and broadcast function
|
||||
connectionManager.broadcastPacket(RoutedPacket(packet))
|
||||
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Failed to send read receipt for message $messageID: ${e.message}")
|
||||
}
|
||||
@@ -708,10 +713,9 @@ class BluetoothMeshService(private val context: Context) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Send Noise identity announcement (broadcast our static public key and signing key)
|
||||
* Now properly formatted as NoiseIdentityAnnouncement to match iOS
|
||||
* Send key exchange to newly connected device
|
||||
*/
|
||||
private fun sendKeyExchangeToDevice() {
|
||||
fun sendKeyExchangeToDevice() {
|
||||
serviceScope.launch {
|
||||
try {
|
||||
val nickname = delegate?.getNickname() ?: myPeerID
|
||||
@@ -743,6 +747,43 @@ class BluetoothMeshService(private val context: Context) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send handshake request to target peer for pending messages
|
||||
*/
|
||||
fun sendHandshakeRequest(targetPeerID: String, pendingCount: UByte) {
|
||||
serviceScope.launch {
|
||||
try {
|
||||
// Create handshake request
|
||||
val request = HandshakeRequest(
|
||||
requesterID = myPeerID,
|
||||
requesterNickname = delegate?.getNickname() ?: myPeerID,
|
||||
targetID = targetPeerID,
|
||||
pendingMessageCount = pendingCount
|
||||
)
|
||||
|
||||
val requestData = request.toBinaryData()
|
||||
|
||||
// Create packet for handshake request
|
||||
val packet = BitchatPacket(
|
||||
version = 1u,
|
||||
type = MessageType.HANDSHAKE_REQUEST.value,
|
||||
senderID = hexStringToByteArray(myPeerID),
|
||||
recipientID = hexStringToByteArray(targetPeerID),
|
||||
timestamp = System.currentTimeMillis().toULong(),
|
||||
payload = requestData,
|
||||
ttl = 6u
|
||||
)
|
||||
|
||||
// Broadcast the packet (Android equivalent of both direct and relay attempts)
|
||||
connectionManager.broadcastPacket(RoutedPacket(packet))
|
||||
Log.d(TAG, "Sent handshake request to $targetPeerID (pending: $pendingCount, ${requestData.size} bytes)")
|
||||
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Failed to send handshake request to $targetPeerID: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a properly formatted NoiseIdentityAnnouncement exactly like iOS
|
||||
*/
|
||||
@@ -822,6 +863,14 @@ class BluetoothMeshService(private val context: Context) {
|
||||
return encryptionService.hasEstablishedSession(peerID)
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate Noise handshake with a specific peer (public API)
|
||||
*/
|
||||
fun initiateNoiseHandshake(peerID: String) {
|
||||
// Delegate to the existing implementation in the MessageHandler delegate
|
||||
messageHandler.delegate?.initiateNoiseHandshake(peerID)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get peer fingerprint for identity management
|
||||
*/
|
||||
|
||||
@@ -63,7 +63,6 @@ class MessageHandler(private val myPeerID: String) {
|
||||
}
|
||||
|
||||
// Check for read receipt with type marker
|
||||
// NOTE: THIS DOESN'T WORK WITH IOS, IT SENDS AN INNER PACKET INSTEAD
|
||||
if (typeMarker == MessageType.READ_RECEIPT.value) {
|
||||
val receiptData = decryptedData.sliceArray(1 until decryptedData.size)
|
||||
val receipt = ReadReceipt.decode(receiptData)
|
||||
|
||||
@@ -139,8 +139,8 @@ class PacketProcessor(private val myPeerID: String) {
|
||||
MessageType.NOISE_HANDSHAKE_INIT -> handleNoiseHandshake(routed, 1)
|
||||
MessageType.NOISE_HANDSHAKE_RESP -> handleNoiseHandshake(routed, 2)
|
||||
MessageType.NOISE_ENCRYPTED -> handleNoiseEncrypted(routed)
|
||||
//MessageType.DELIVERY_ACK -> handleDeliveryAck(routed) // custom packet type...
|
||||
MessageType.READ_RECEIPT -> handleReadReceipt(routed)
|
||||
// MessageType.DELIVERY_ACK -> handleDeliveryAck(routed) // custom packet type...
|
||||
// MessageType.READ_RECEIPT -> handleReadReceipt(routed)
|
||||
else -> {
|
||||
validPacket = false
|
||||
Log.w(TAG, "Unknown message type: ${packet.type}")
|
||||
|
||||
Reference in New Issue
Block a user