handshake works

This commit is contained in:
CC
2026-06-09 01:01:39 +02:00
parent b4df0d7cf1
commit b22629faa4
4 changed files with 258 additions and 42 deletions
@@ -93,8 +93,8 @@ class ChatViewModel(
// Create Noise session delegate for clean dependency injection
private val noiseSessionDelegate = object : NoiseSessionDelegate {
override fun hasEstablishedSession(peerID: String): Boolean = meshService.hasEstablishedSession(peerID)
override fun initiateHandshake(peerID: String) = meshService.initiateNoiseHandshake(peerID)
override fun hasEstablishedSession(peerID: String): Boolean = hasEstablishedSessionOnAnyLocalTransport(peerID)
override fun initiateHandshake(peerID: String) = initiateNoiseHandshakeOnBestLocalTransport(peerID)
override fun getMyPeerID(): String = meshService.myPeerID
}
@@ -490,7 +490,7 @@ class ChatViewModel(
meshService.sendMessage(messageContent, mentions, channel)
try { com.bitchat.android.wifiaware.WifiAwareController.getService()?.sendMessage(messageContent, mentions, channel) } catch (_: Exception) {}
}
})
}, this)
return
}
@@ -520,7 +520,7 @@ class ChatViewModel(
}
}
// Send private message
val recipientNickname = meshService.getPeerNicknames()[selectedPeer]
val recipientNickname = nicknameForPeer(selectedPeer)
privateChatManager.sendPrivateMessage(
content,
selectedPeer,
@@ -661,6 +661,79 @@ class ChatViewModel(
Log.i("ChatViewModel", "Peer fingerprints: ${privateChatManager.getAllPeerFingerprints()}")
Log.i("ChatViewModel", "==============================")
}
private fun getWifiAwareService(): com.bitchat.android.mesh.MeshService? {
return try { com.bitchat.android.wifiaware.WifiAwareController.getService() } catch (_: Exception) { null }
}
private fun isConnectedOnMesh(peerID: String): Boolean {
return try {
meshService.getPeerInfo(peerID)?.isConnected == true
} catch (_: Exception) {
false
}
}
private fun isConnectedOnService(service: com.bitchat.android.mesh.MeshService?, peerID: String): Boolean {
return try {
service != null && service.getPeerInfo(peerID)?.isConnected == true
} catch (_: Exception) {
false
}
}
private fun hasEstablishedSessionOnMesh(peerID: String): Boolean {
return try {
meshService.getPeerInfo(peerID)?.isConnected == true &&
meshService.hasEstablishedSession(peerID)
} catch (_: Exception) {
false
}
}
private fun hasEstablishedSessionOnService(service: com.bitchat.android.mesh.MeshService?, peerID: String): Boolean {
return try {
service != null &&
service.getPeerInfo(peerID)?.isConnected == true &&
service.hasEstablishedSession(peerID)
} catch (_: Exception) {
false
}
}
private fun hasEstablishedSessionOnAnyLocalTransport(peerID: String): Boolean {
return hasEstablishedSessionOnMesh(peerID) ||
hasEstablishedSessionOnService(getWifiAwareService(), peerID)
}
private fun initiateNoiseHandshakeOnBestLocalTransport(peerID: String) {
val aware = getWifiAwareService()
when {
isConnectedOnMesh(peerID) -> meshService.initiateNoiseHandshake(peerID)
isConnectedOnService(aware, peerID) -> aware?.initiateNoiseHandshake(peerID)
else -> meshService.initiateNoiseHandshake(peerID)
}
}
private fun nicknameForPeer(peerID: String): String? {
return state.peerNicknames.value[peerID]
?: try { meshService.getPeerNicknames()[peerID] } catch (_: Exception) { null }
?: try { getWifiAwareService()?.getPeerNicknames()?.get(peerID) } catch (_: Exception) { null }
}
private fun sessionStateForPeer(peerID: String): NoiseSession.NoiseSessionState {
val meshState = try { meshService.getSessionState(peerID) } catch (_: Exception) { NoiseSession.NoiseSessionState.Uninitialized }
val awareState = try { getWifiAwareService()?.getSessionState(peerID) } catch (_: Exception) { null }
return when {
meshState is NoiseSession.NoiseSessionState.Established -> meshState
awareState is NoiseSession.NoiseSessionState.Established -> awareState
meshState is NoiseSession.NoiseSessionState.Handshaking -> meshState
awareState is NoiseSession.NoiseSessionState.Handshaking -> awareState
meshState !is NoiseSession.NoiseSessionState.Uninitialized -> meshState
awareState != null -> awareState
else -> meshState
}
}
/**
* Initialize session state monitoring for reactive UI updates
@@ -685,7 +758,7 @@ class ChatViewModel(
// Update session states
val prevStates = state.getPeerSessionStatesValue()
val sessionStates = currentPeers.associateWith { peerID ->
meshService.getSessionState(peerID).toString()
sessionStateForPeer(peerID).toString()
}
state.setPeerSessionStates(sessionStates)
// Detect new established sessions and flush router outbox for them and their noiseHex aliases
@@ -736,7 +809,7 @@ class ChatViewModel(
// Flush any pending QR verification once a Noise session is established
currentPeers.forEach { peerID ->
if (meshService.getSessionState(peerID) is NoiseSession.NoiseSessionState.Established) {
if (sessionStateForPeer(peerID) is NoiseSession.NoiseSessionState.Established) {
verificationHandler.sendPendingVerificationIfNeeded(peerID)
}
}
@@ -36,14 +36,14 @@ class CommandProcessor(
val cmd = parts.first().lowercase()
when (cmd) {
"/j", "/join" -> handleJoinCommand(parts, myPeerID)
"/m", "/msg" -> handleMessageCommand(parts, meshService)
"/m", "/msg" -> handleMessageCommand(parts, meshService, viewModel)
"/w" -> handleWhoCommand(meshService, viewModel)
"/clear" -> handleClearCommand()
"/pass" -> handlePassCommand(parts, myPeerID)
"/block" -> handleBlockCommand(parts, meshService)
"/unblock" -> handleUnblockCommand(parts, meshService)
"/hug" -> handleActionCommand(parts, "gives", "a warm hug 🫂", meshService, myPeerID, onSendMessage)
"/slap" -> handleActionCommand(parts, "slaps", "around a bit with a large trout 🐟", meshService, myPeerID, onSendMessage)
"/hug" -> handleActionCommand(parts, "gives", "a warm hug 🫂", meshService, myPeerID, onSendMessage, viewModel)
"/slap" -> handleActionCommand(parts, "slaps", "around a bit with a large trout 🐟", meshService, myPeerID, onSendMessage, viewModel)
"/channels" -> handleChannelsCommand()
else -> handleUnknownCommand(cmd)
}
@@ -77,7 +77,7 @@ class CommandProcessor(
}
}
private fun handleMessageCommand(parts: List<String>, meshService: BluetoothMeshService) {
private fun handleMessageCommand(parts: List<String>, meshService: BluetoothMeshService, viewModel: ChatViewModel?) {
if (parts.size > 1) {
val targetName = parts[1].removePrefix("@")
val peerID = getPeerIDForNickname(targetName, meshService)
@@ -96,8 +96,7 @@ class CommandProcessor(
state.getNicknameValue(),
getMyPeerID(meshService)
) { content, peerIdParam, recipientNicknameParam, messageId ->
// This would trigger the actual mesh service send
sendPrivateMessageVia(meshService, content, peerIdParam, recipientNicknameParam, messageId)
sendPrivateMessageVia(meshService, content, peerIdParam, recipientNicknameParam, messageId, viewModel)
}
} else {
val systemMessage = BitchatMessage(
@@ -286,7 +285,8 @@ class CommandProcessor(
object_: String,
meshService: BluetoothMeshService,
myPeerID: String,
onSendMessage: (String, List<String>, String?) -> Unit
onSendMessage: (String, List<String>, String?) -> Unit,
viewModel: ChatViewModel?
) {
if (parts.size > 1) {
val targetName = parts[1].removePrefix("@")
@@ -306,7 +306,7 @@ class CommandProcessor(
state.getNicknameValue(),
myPeerID
) { content, peerIdParam, recipientNicknameParam, messageId ->
sendPrivateMessageVia(meshService, content, peerIdParam, recipientNicknameParam, messageId)
sendPrivateMessageVia(meshService, content, peerIdParam, recipientNicknameParam, messageId, viewModel)
}
} else if (isInLocationChannel) {
// Let the transport layer add the echo; just send it out
@@ -505,17 +505,41 @@ class CommandProcessor(
private fun getPeerIDForNickname(nickname: String, meshService: BluetoothMeshService): String? {
return meshService.getPeerNicknames().entries.find { it.value == nickname }?.key
?: try {
com.bitchat.android.wifiaware.WifiAwareController.getService()
?.getPeerNicknames()
?.entries
?.find { it.value == nickname }
?.key
} catch (_: Exception) {
null
}
}
private fun getPeerNickname(peerID: String, meshService: BluetoothMeshService): String {
return meshService.getPeerNicknames()[peerID] ?: peerID
return meshService.getPeerNicknames()[peerID]
?: try { com.bitchat.android.wifiaware.WifiAwareController.getService()?.getPeerNicknames()?.get(peerID) } catch (_: Exception) { null }
?: peerID
}
private fun getMyPeerID(meshService: BluetoothMeshService): String {
return meshService.myPeerID
}
private fun sendPrivateMessageVia(meshService: BluetoothMeshService, content: String, peerID: String, recipientNickname: String, messageId: String) {
meshService.sendPrivateMessage(content, peerID, recipientNickname, messageId)
private fun sendPrivateMessageVia(
meshService: BluetoothMeshService,
content: String,
peerID: String,
recipientNickname: String,
messageId: String,
viewModel: ChatViewModel?
) {
if (viewModel != null) {
com.bitchat.android.services.MessageRouter
.getInstance(viewModel.getApplication(), meshService)
.sendPrivate(content, peerID, recipientNickname, messageId)
} else {
meshService.sendPrivateMessage(content, peerID, recipientNickname, messageId)
}
}
}