topo_group_connect: infinite reconnect cycle + connecting status for GUI
- dedup double ETCP_CONN_STATUS_UP (UDP+TCP links) in topo_group_new_conn - close conn_mgr handle on TIMEOUT in Phase2/3 (fix stuck 'already connecting') - infinite Phase1→2→3 cycle with pause (1s active / 30s standby) - CHAT_EVT_CONNECTING_NODES: yellow circle in member list while connecting - Android: client_activity wiring via onStart/onStop + nativeSetActive - function-level comments in topo_group_connect.c
This commit is contained in:
1 parent
54ad03185b
commit
0492b19468
9 files changed
+159
-6
No files matched your search
@@ -146,4 +146,14 @@ class MainActivity : ComponentActivity() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
if (NativeLib.isReady()) NativeLib.setActive(true)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
if (NativeLib.isReady()) NativeLib.setActive(false)
|
||||
}
|
||||
}
|
||||
@@ -68,7 +68,7 @@ data class ChatMember(val nodeId: Long, val name: String, val online: Boolean =
|
||||
val directUp: Boolean = false, val indirectUp: Boolean = false,
|
||||
val directPresence: Boolean = false, val indirectPresence: Boolean = false,
|
||||
val bgpPresence: Boolean = false, val bgpRtt: Int = 0,
|
||||
val bgpNodes: Int = 0) {
|
||||
val bgpNodes: Int = 0, val connecting: Boolean = false) {
|
||||
val flags: Int get() = (if (isSuper) 1 else 0) or (if (isAdmin) 2 else 0) or (if (isModer) 4 else 0)
|
||||
}
|
||||
|
||||
|
||||
@@ -53,6 +53,9 @@ object NativeLib {
|
||||
fun ping() { nativePing() }
|
||||
fun isResponsive(): Boolean = nativeIsResponsive()
|
||||
|
||||
/* ── App foreground/background (Android lifecycle) ── */
|
||||
fun setActive(active: Boolean) { nativeSetActive(active) }
|
||||
|
||||
fun sendMessage(channelId: String, text: String) { nativeSendMessage(channelId, text) }
|
||||
fun createChannel(name: String, channelId: String) { nativeCreateChannel(name, channelId) }
|
||||
fun connectNode(address: String, port: Int, pubkeyHex: String) { nativeConnectNode(address, port, pubkeyHex) }
|
||||
@@ -140,6 +143,7 @@ object NativeLib {
|
||||
private external fun nativePing()
|
||||
private external fun nativeIsResponsive(): Boolean
|
||||
private external fun nativeIsRunning(): Boolean
|
||||
private external fun nativeSetActive(active: Boolean)
|
||||
|
||||
/* ── Channel members JNI ── */
|
||||
private external fun nativeGetChannelMembers(channelId: String): String?
|
||||
|
||||
@@ -122,11 +122,13 @@ private fun MemberListItem(
|
||||
onEdit: () -> Unit
|
||||
) {
|
||||
val onlineColor = when {
|
||||
member.connecting -> Color(0xFFFFEB3B) // yellow: connecting
|
||||
member.directUp || member.indirectUp -> Color(0xFF4CAF50) // green: up
|
||||
member.directPresence || member.indirectPresence || member.bgpPresence -> Color(0xFFFFA726) // orange: presence but down
|
||||
else -> Color(0xFF9E9E9E) // gray: offline
|
||||
}
|
||||
val connLabel = when {
|
||||
member.connecting -> "connecting"
|
||||
member.directUp -> "direct"
|
||||
member.indirectUp -> "indirect"
|
||||
member.directPresence || member.indirectPresence || member.bgpPresence -> "offline"
|
||||
@@ -171,6 +173,7 @@ private fun MemberListItem(
|
||||
if (member.isSuper) parts.add("Super")
|
||||
if (member.isStorage) parts.add("Storage")
|
||||
if (member.isSelf) parts.add("self")
|
||||
else if (member.connecting) parts.add("connecting…")
|
||||
else if (member.directUp) parts.add("direct↑")
|
||||
else if (member.indirectUp) parts.add("indirect↑")
|
||||
else if (member.directPresence || member.indirectPresence || member.bgpPresence) parts.add("down")
|
||||
|
||||
@@ -65,6 +65,9 @@ class ChatViewModel : ViewModel() {
|
||||
private val _nodeStatuses = MutableStateFlow<Map<Long, NodeStatus>>(emptyMap())
|
||||
val nodeStatuses: StateFlow<Map<Long, NodeStatus>> = _nodeStatuses
|
||||
|
||||
private val _connecting = MutableStateFlow<Map<String, Set<Long>>>(emptyMap())
|
||||
val connecting: StateFlow<Map<String, Set<Long>>> = _connecting
|
||||
|
||||
private val _localSockets = MutableStateFlow<List<LocalSocketState>>(emptyList())
|
||||
val localSockets: StateFlow<List<LocalSocketState>> = _localSockets
|
||||
|
||||
@@ -281,6 +284,24 @@ class ChatViewModel : ViewModel() {
|
||||
_selectedMember.value = _selectedMember.value?.copy(online = ml.connected && ml.linksUp > 0)
|
||||
}
|
||||
}
|
||||
27 -> { /* CONNECTING_NODES: [ch_id_len:1][ch_id:var][count:2][node_id:8]* */
|
||||
if (data == null || data.size < 3) return
|
||||
val cl = data[0].toInt() and 0xFF
|
||||
if (data.size < 1 + cl + 2) 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 count = buf.getShort().toInt() and 0xFFFF
|
||||
val set = HashSet<Long>()
|
||||
for (i in 0 until count) {
|
||||
if (buf.position() + 8 > data.size) break
|
||||
set.add(buf.getLong())
|
||||
}
|
||||
_connecting.value = _connecting.value + (chId to set)
|
||||
val cur = _currentChannel.value
|
||||
if (cur != null && cur.id == chId) {
|
||||
_members.value = _members.value.map { it.copy(connecting = it.nodeId in set) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,17 +345,19 @@ class ChatViewModel : ViewModel() {
|
||||
fun refreshMembers(chId: String) {
|
||||
val r = repo ?: return
|
||||
val statuses = _nodeStatuses.value
|
||||
val connecting = _connecting.value[chId] ?: emptySet()
|
||||
viewModelScope.launch {
|
||||
val raw = withContext(Dispatchers.IO) { r.getMembers(chId) }
|
||||
_members.value = raw.map { m ->
|
||||
val ns = statuses[m.nodeId]
|
||||
if (ns != null) m.copy(
|
||||
val base = if (ns != null) m.copy(
|
||||
online = ns.online, rtt = ns.bestRtt,
|
||||
directUp = ns.directUp, indirectUp = ns.indirectUp,
|
||||
directPresence = ns.directPresence, indirectPresence = ns.indirectPresence,
|
||||
bgpPresence = ns.bgpPresence, bgpRtt = ns.bgpRtt,
|
||||
bgpNodes = ns.bgpNodes
|
||||
) else m
|
||||
base.copy(connecting = base.nodeId in connecting)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user