Browse Source

Update Android consumers for extended member snapshots

master
evgeny 1 week ago
parent
commit
ae461e746f
  1. 8
      doc/member_files.txt
  2. 16
      tools/chatgui-android/app/src/main/java/com/utun/chat/data/ChatRepository.kt
  3. 10
      tools/chatgui-android/app/src/main/java/com/utun/chat/viewmodel/ChatViewModel.kt

8
doc/member_files.txt

@ -316,10 +316,10 @@ AvatarManager общий для списка участников и сообщ
test_avatars проверяет нормализацию, хеш/размеры, очистку temp, настоящее storage test_avatars проверяет нормализацию, хеш/размеры, очистку temp, настоящее storage
в двух каналах, публикацию, сохранение при смене имени, DM-кеш, restart без сети, в двух каналах, публикацию, сохранение при смене имени, DM-кеш, restart без сети,
автоматический download после потери кеша и удаление ссылок. test_member_adapter автоматический download после потери кеша и удаление ссылок. Также проверяются
Проверяет также max_bytes до открытия local temp и смену аватарки при задержанном max_bytes до открытия local temp и смена аватарки при задержанном download старой
download старой версии: поздний результат не заменяет новый рисунок. версии: поздний результат не заменяет новый рисунок. test_member_adapter проверяет
проверяет подписанные профили 191/255/256/512/1023/1024 байт вместе с adm_tags до 8192. подписанные профили 191/255/256/512/1023/1024 байт вместе с adm_tags до 8192.
Категория media=debug показывает discovery, cache hit/eviction, направление, Категория media=debug показывает discovery, cache hit/eviction, направление,
group/owner/server/hash, ошибки проверки и retry; media=info — передачи/публикации. group/owner/server/hash, ошибки проверки и retry; media=info — передачи/публикации.

16
tools/chatgui-android/app/src/main/java/com/utun/chat/data/ChatRepository.kt

@ -161,16 +161,18 @@ fun parseConnList(data: ByteArray): List<ConnInfo> {
return list return list
} }
/* ── Member wire format (79 bytes, from chat_member.h) ── */ /* Размер общего снимка из chat_member.h; одинаковый для desktop и Android. */
const val MEMBER_WIRE_SIZE = 157
data class MemberWire( data class MemberWire(
val nodeId: Long, val online: Int, val isSelf: Boolean, val nodeId: Long, val online: Int, val isSelf: Boolean,
val flags: Int, val rtt: Int, val natType: Int, val flags: Int, val rtt: Int, val natType: Int,
val storage: Boolean, val name: String val storage: Boolean, val name: String,
val avatarServer: Long = 0, val avatarFile: String = "", val storageRole: Boolean = false
) )
fun parseMemberWire(data: ByteArray, offset: Int = 0): MemberWire? { fun parseMemberWire(data: ByteArray, offset: Int = 0): MemberWire? {
if (offset < 0 || offset > data.size - 79) return null if (offset < 0 || offset > data.size - MEMBER_WIRE_SIZE) return null
val buf = ByteBuffer.wrap(data, offset, 79).order(ByteOrder.LITTLE_ENDIAN) val buf = ByteBuffer.wrap(data, offset, MEMBER_WIRE_SIZE).order(ByteOrder.LITTLE_ENDIAN)
val nodeId = buf.getLong() val nodeId = buf.getLong()
val online = buf.get().toInt() and 0xFF val online = buf.get().toInt() and 0xFF
val isSelf = buf.get().toInt() != 0 val isSelf = buf.get().toInt() != 0
@ -180,7 +182,11 @@ fun parseMemberWire(data: ByteArray, offset: Int = 0): MemberWire? {
val storage = buf.get().toInt() != 0 val storage = buf.get().toInt() != 0
val nameBytes = ByteArray(64); buf.get(nameBytes) val nameBytes = ByteArray(64); buf.get(nameBytes)
val name = String(nameBytes).trimEnd('\u0000') val name = String(nameBytes).trimEnd('\u0000')
return MemberWire(nodeId, online, isSelf, flags, rtt, natType, storage, name) val avatarServer = buf.getLong()
val avatarBytes = ByteArray(69); buf.get(avatarBytes)
val avatarFile = String(avatarBytes).trimEnd('\u0000')
val storageRole = buf.get().toInt() != 0
return MemberWire(nodeId, online, isSelf, flags, rtt, natType, storage, name, avatarServer, avatarFile, storageRole)
} }
/* Wire не содержит verified/nodeType и состояния транспортов: сохраняем их из текущей строки. */ /* Wire не содержит verified/nodeType и состояния транспортов: сохраняем их из текущей строки. */

10
tools/chatgui-android/app/src/main/java/com/utun/chat/viewmodel/ChatViewModel.kt

@ -467,11 +467,11 @@ class ChatViewModel : ViewModel() {
val chId = String(data, 1, cl) val chId = String(data, 1, cl)
val count = (data[1 + cl].toInt() and 0xFF) or ((data[2 + cl].toInt() and 0xFF) shl 8) val count = (data[1 + cl].toInt() and 0xFF) or ((data[2 + cl].toInt() and 0xFF) shl 8)
val offset = cl + 3 val offset = cl + 3
if (data.size != offset + count * 79) { if (data.size != offset + count * MEMBER_WIRE_SIZE) {
LogManager.addLog("ERROR", "VM", "MEMBER_LIST: invalid size ch=$chId count=$count bytes=${data.size}"); return LogManager.addLog("ERROR", "VM", "MEMBER_LIST: invalid size ch=$chId count=$count bytes=${data.size}"); return
} }
val radios = (0 until count).associate { i -> val radios = (0 until count).associate { i ->
val w = requireNotNull(parseMemberWire(data, offset + i * 79)) val w = requireNotNull(parseMemberWire(data, offset + i * MEMBER_WIRE_SIZE))
w.nodeId to ((w.flags and 0x10) != 0) w.nodeId to ((w.flags and 0x10) != 0)
} }
memberRadios[chId] = radios memberRadios[chId] = radios
@ -479,12 +479,12 @@ class ChatViewModel : ViewModel() {
_members.value = _members.value.map { it.copy(radioActive = radios[it.nodeId] == true) } _members.value = _members.value.map { it.copy(radioActive = radios[it.nodeId] == true) }
LogManager.addLog("DEBUG", "VM", "MEMBER_LIST: ch=$chId members=$count radios=${radios.values.count { it }}") LogManager.addLog("DEBUG", "VM", "MEMBER_LIST: ch=$chId members=$count radios=${radios.values.count { it }}")
} }
24 -> { /* MEMBER_UPDATED: [ch_id_len:1][ch_id:var][count:1][member:79B] */ 24 -> { /* MEMBER_UPDATED: [ch_id_len:1][ch_id:var][count:1][member:MEMBER_WIRE_SIZE] */
if (data == null || data.size < 3 + 79) { if (data == null || data.size < 3 + MEMBER_WIRE_SIZE) {
LogManager.addLog("ERROR", "VM", "MEMBER_UPDATED: missing header/member"); return LogManager.addLog("ERROR", "VM", "MEMBER_UPDATED: missing header/member"); return
} }
val cl = data[0].toInt() and 0xFF val cl = data[0].toInt() and 0xFF
if (cl == 0 || data.size != cl + 2 + 79 || data[cl + 1].toInt() != 1) { if (cl == 0 || data.size != cl + 2 + MEMBER_WIRE_SIZE || data[cl + 1].toInt() != 1) {
LogManager.addLog("ERROR", "VM", "MEMBER_UPDATED: invalid payload channelLength=$cl bytes=${data.size}"); return LogManager.addLog("ERROR", "VM", "MEMBER_UPDATED: invalid payload channelLength=$cl bytes=${data.size}"); return
} }
val chId = String(data, 1, cl) val chId = String(data, 1, cl)

Loading…
Cancel
Save