android: DoT closes the per-worker connection on any read error or id mismatch (a late reply would answer the next query and desync it forever); the connect probe no longer does an untimed host lookup for the log

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
DenozordecandClaude Opus 5.5 committed 2026-11-09 20:26:41 +07:00
1 parent 59d989e956
commit c5c5f5d461
1 file changed
+16 -13
@@ -233,20 +233,12 @@ object SecureDns
{
return true
}
val upstream = try
{
InetAddress.getAllByName(config.host).joinToString(",") { it.hostAddress ?: "" }
}
catch (e: Exception)
{
"unresolved"
}
val result = probe(config)
probedConfig = config
probedAt = now
probeOk = result.ok
DiagLog.i(TAG, if (result.ok) "probe ${config.label} ok in ${result.ms} ms (upstream $upstream)"
else "probe ${config.label} failed after ${result.ms} ms (upstream $upstream): ${result.error}; falling back to plain DNS")
DiagLog.i(TAG, if (result.ok) "probe ${config.label} ok in ${result.ms} ms"
else "probe ${config.label} failed after ${result.ms} ms: ${result.error}; falling back to plain DNS")
return result.ok
}
@@ -430,9 +422,20 @@ object SecureDns
dot.get()?.close()
dot.set(it)
}
conn.out.write(SecureDnsCodec.frame(query))
conn.out.flush()
return SecureDnsCodec.readFrame(conn.input)
try
{
conn.out.write(SecureDnsCodec.frame(query))
conn.out.flush()
val reply = SecureDnsCodec.readFrame(conn.input)
if (!SecureDnsCodec.sameId(query, reply)) throw IOException("reply id mismatch")
return reply
}
catch (e: IOException)
{ /* a late reply would stay in the stream and answer the next query: never reuse it */
conn.close()
dot.set(null)
throw e
}
}
private class DotConnection(val config: SecureDnsConfig, val socket: SSLSocket)