Commit 14f386ca authored by Mygod's avatar Mygod

Prevent remote resolving failure kills entire resolver

parent 3e61fdb7
...@@ -99,23 +99,23 @@ class LocalDnsServer(private val localResolver: suspend (String) -> Array<InetAd ...@@ -99,23 +99,23 @@ class LocalDnsServer(private val localResolver: suspend (String) -> Array<InetAd
printLog(e) printLog(e)
return forward(packet) return forward(packet)
} }
return coroutineScope { return supervisorScope {
val remote = async { withTimeout(TIMEOUT) { forward(packet) } } val remote = async { withTimeout(TIMEOUT) { forward(packet) } }
try { try {
if (forwardOnly || request.header.opcode != Opcode.QUERY) return@coroutineScope remote.await() if (forwardOnly || request.header.opcode != Opcode.QUERY) return@supervisorScope remote.await()
val question = request.question val question = request.question
if (question?.type != Type.A) return@coroutineScope remote.await() if (question?.type != Type.A) return@supervisorScope remote.await()
val host = question.name.toString(true) val host = question.name.toString(true)
if (remoteDomainMatcher?.containsMatchIn(host) == true) return@coroutineScope remote.await() if (remoteDomainMatcher?.containsMatchIn(host) == true) return@supervisorScope remote.await()
val localResults = try { val localResults = try {
withTimeout(TIMEOUT) { GlobalScope.async(Dispatchers.IO) { localResolver(host) }.await() } withTimeout(TIMEOUT) { GlobalScope.async(Dispatchers.IO) { localResolver(host) }.await() }
} catch (_: TimeoutCancellationException) { } catch (_: TimeoutCancellationException) {
Crashlytics.log(Log.WARN, TAG, "Local resolving timed out, falling back to remote resolving") Crashlytics.log(Log.WARN, TAG, "Local resolving timed out, falling back to remote resolving")
return@coroutineScope remote.await() return@supervisorScope remote.await()
} catch (_: UnknownHostException) { } catch (_: UnknownHostException) {
return@coroutineScope remote.await() return@supervisorScope remote.await()
} }
if (localResults.isEmpty()) return@coroutineScope remote.await() if (localResults.isEmpty()) return@supervisorScope remote.await()
if (localIpMatcher.isEmpty() || localIpMatcher.any { subnet -> localResults.any(subnet::matches) }) { if (localIpMatcher.isEmpty() || localIpMatcher.any { subnet -> localResults.any(subnet::matches) }) {
remote.cancel() remote.cancel()
ByteBuffer.wrap(prepareDnsResponse(request).apply { ByteBuffer.wrap(prepareDnsResponse(request).apply {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment