From 2b2434d23990522c408acacaef6909e27068aeda Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 18 Dec 2025 01:58:16 +0100 Subject: [PATCH] fix(android): decode UTF-8 TXT records --- .../clawdis/node/bridge/BridgeDiscovery.kt | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/apps/android/app/src/main/java/com/steipete/clawdis/node/bridge/BridgeDiscovery.kt b/apps/android/app/src/main/java/com/steipete/clawdis/node/bridge/BridgeDiscovery.kt index a93b86c68..ca9c5ef39 100644 --- a/apps/android/app/src/main/java/com/steipete/clawdis/node/bridge/BridgeDiscovery.kt +++ b/apps/android/app/src/main/java/com/steipete/clawdis/node/bridge/BridgeDiscovery.kt @@ -11,6 +11,8 @@ import android.os.CancellationSignal import android.util.Log import java.io.IOException import java.net.InetSocketAddress +import java.nio.ByteBuffer +import java.nio.charset.CodingErrorAction import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.Executor import java.util.concurrent.Executors @@ -424,7 +426,7 @@ class BridgeDiscovery( emptyList() } for (s in strings) { - val trimmed = s.trim() + val trimmed = decodeDnsTxtString(s).trim() if (trimmed.startsWith(prefix)) { return trimmed.removePrefix(prefix).trim().ifEmpty { null } } @@ -433,6 +435,22 @@ class BridgeDiscovery( return null } + private fun decodeDnsTxtString(raw: String): String { + // dnsjava treats TXT as opaque bytes and decodes as ISO-8859-1 to preserve bytes. + // Our TXT payload is UTF-8 (written by the gateway), so re-decode when possible. + val bytes = raw.toByteArray(Charsets.ISO_8859_1) + val decoder = + Charsets.UTF_8 + .newDecoder() + .onMalformedInput(CodingErrorAction.REPORT) + .onUnmappableCharacter(CodingErrorAction.REPORT) + return try { + decoder.decode(ByteBuffer.wrap(bytes)).toString() + } catch (_: Throwable) { + raw + } + } + private suspend fun resolveHostUnicast(hostname: String): String? { val a = records(lookupUnicastMessage(hostname, Type.A), Section.ANSWER)