Fix ETCP session recovery and router lifecycle; confirm chat invites before publishing

This commit is contained in:
evgeny committed 2026-09-27 02:51:47 +03:00
1 parent 018c8e795d
commit 3131dcbb7c
67 files changed
+3005 -1249

No files matched your search

@@ -54,7 +54,7 @@ object NativeLib {
fun getMyNodeId(): Long = nativeGetMyNodeId()
fun requestInviteCandidates(channelId: String) { nativeRequestInviteCandidates(channelId) }
fun requestInviteLink(channelId: String, targetNodeId: Long) { nativeRequestInviteLink(channelId, targetNodeId) }
fun requestInviteLink(channelId: String, targetNodeId: Long, requestId: Long) { nativeRequestInviteLink(channelId, targetNodeId, requestId) }
fun ping() { nativePing() }
fun isResponsive(): Boolean = nativeIsResponsive()
@@ -198,7 +198,7 @@ object NativeLib {
private external fun nativeClearDatabase(): Boolean
private external fun nativeGetMyNodeId(): Long
private external fun nativeRequestInviteCandidates(channelId: String)
private external fun nativeRequestInviteLink(channelId: String, targetNodeId: Long)
private external fun nativeRequestInviteLink(channelId: String, targetNodeId: Long, requestId: Long)
private external fun nativeRestart(configText: String): Boolean
private external fun nativeUpdateSockets(configText: String): Boolean
private external fun nativePing()
@@ -136,6 +136,8 @@ class ChatViewModel : ViewModel() {
private val _inviteLink = MutableStateFlow<String?>(null)
val inviteLink: StateFlow<String?> = _inviteLink
private var inviteRequestId = 0L
private var inviteChannelId: String? = null
private val _inviteLinkPending = MutableStateFlow(false)
val inviteLinkPending: StateFlow<Boolean> = _inviteLinkPending
@@ -466,6 +468,7 @@ class ChatViewModel : ViewModel() {
val cl = data[0].toInt() and 0xFF
if (data.size < 1 + cl + 10) return
val chId = String(data, 1, cl)
if (inviteChannelId != chId) return
val buf = java.nio.ByteBuffer.wrap(data, 1 + cl, data.size - 1 - cl).order(java.nio.ByteOrder.LITTLE_ENDIAN)
val autoId = buf.long
val count = buf.short.toInt() and 0xFFFF
@@ -487,21 +490,22 @@ class ChatViewModel : ViewModel() {
if (id == autoId) continue
list.add(InviteCandidate(id, label(id), isSelf = id == myId))
}
if (inviteChannelId != chId) return@launch
_inviteCandidates.value = list
NativeLib.requestInviteLink(chId, autoId)
_inviteLink.value = null
_inviteLinkPending.value = true
if (inviteChannelId == chId) requestInviteLink(chId, autoId)
}
}
29 -> { /* INVITE_LINK_READY: [ch_id_len:1][ch_id][link_len:2][link] — пустой link = ошибка */
if (data == null || data.size < 4) return
29 -> { /* [ch_id_len:1][ch_id][request_id:8][link_len:2][link] */
if (data == null || data.size < 11) return
val cl = data[0].toInt() and 0xFF
if (data.size < 1 + cl + 2) return
if (data.size < 1 + cl + 10) return
val chId = String(data, 1, cl)
val buf = java.nio.ByteBuffer.wrap(data, 1 + cl, data.size - 1 - cl).order(java.nio.ByteOrder.LITTLE_ENDIAN)
val requestId = buf.long
if (chId != inviteChannelId || requestId != inviteRequestId) return
val linkLen = buf.short.toInt() and 0xFFFF
val link = if (linkLen > 0 && data.size >= 1 + cl + 2 + linkLen)
String(data, 1 + cl + 2, linkLen) else null
val link = if (linkLen > 0 && buf.remaining() >= linkLen)
String(data, 1 + cl + 10, linkLen) else null
LogManager.addLog(if (link != null) "INFO" else "ERROR", "VM", "INVITE_LINK_READY ch=$chId len=$linkLen")
_inviteLink.value = link
_inviteLinkPending.value = false
@@ -839,6 +843,8 @@ class ChatViewModel : ViewModel() {
}
fun requestInvite(channelId: String) {
inviteChannelId = channelId
inviteRequestId++
_inviteCandidates.value = emptyList()
_inviteLink.value = null
_inviteLinkPending.value = true
@@ -849,11 +855,14 @@ class ChatViewModel : ViewModel() {
fun requestInviteLink(channelId: String, targetNodeId: Long) {
_inviteLink.value = null
_inviteLinkPending.value = true
NativeLib.requestInviteLink(channelId, targetNodeId)
inviteChannelId = channelId
NativeLib.requestInviteLink(channelId, targetNodeId, ++inviteRequestId)
LogManager.addLog("INFO", "VM", "requestInviteLink ch=$channelId node=0x%016x".format(targetNodeId))
}
fun clearInvite() {
inviteChannelId = null
inviteRequestId++
_inviteCandidates.value = emptyList()
_inviteLink.value = null
_inviteLinkPending.value = false