From c8a89faa8d08d6245a554ab077eec06132d3b1eb Mon Sep 17 00:00:00 2001 From: M66B Date: Sat, 5 Sep 2020 22:32:32 +0200 Subject: [PATCH] Use Android DNS resolver (experimental) --- .../java/eu/faircode/email/DnsHelper.java | 60 ++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/eu/faircode/email/DnsHelper.java b/app/src/main/java/eu/faircode/email/DnsHelper.java index 2f647244fb..d2a3756298 100644 --- a/app/src/main/java/eu/faircode/email/DnsHelper.java +++ b/app/src/main/java/eu/faircode/email/DnsHelper.java @@ -21,6 +21,7 @@ package eu.faircode.email; import android.content.Context; import android.net.ConnectivityManager; +import android.net.DnsResolver; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkInfo; @@ -30,16 +31,20 @@ import androidx.annotation.NonNull; import org.xbill.DNS.Lookup; import org.xbill.DNS.MXRecord; +import org.xbill.DNS.Message; import org.xbill.DNS.Record; import org.xbill.DNS.SRVRecord; import org.xbill.DNS.SimpleResolver; import org.xbill.DNS.TextParseException; import org.xbill.DNS.Type; +import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; import javax.mail.Address; import javax.mail.internet.InternetAddress; @@ -115,7 +120,60 @@ public class DnsHelper { } try { - SimpleResolver resolver = new SimpleResolver(getDnsServer(context)); + SimpleResolver resolver = new SimpleResolver(getDnsServer(context)) { + private IOException ex; + private Message result; + + @Override + public Message send(Message query) throws IOException { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || !BuildConfig.DEBUG) + return super.send(query); + else { + Log.i("Using Android DNS resolver"); + Semaphore sem = new Semaphore(0); + DnsResolver resolver = DnsResolver.getInstance(); + resolver.rawQuery( + null, + query.toWire(), + DnsResolver.FLAG_EMPTY, + Helper.getBackgroundExecutor(1, "dns"), + null, + new DnsResolver.Callback() { + @Override + public void onAnswer(@NonNull byte[] answer, int rcode) { + Log.i("DNS rcode=" + rcode); + try { + if (rcode == 0) + result = new Message(answer); + else + throw new IOException("rcode=" + rcode); + } catch (Throwable e) { + ex = new IOException(e.getMessage()); + } + sem.release(); + } + + @Override + public void onError(@NonNull DnsResolver.DnsException e) { + Log.w(e); + ex = new IOException(e.getMessage()); + sem.release(); + } + }); + try { + if (!sem.tryAcquire(LOOKUP_TIMEOUT, TimeUnit.SECONDS)) + throw new IOException("timeout"); + } catch (InterruptedException e) { + ex = new IOException("interrupted"); + } + + if (ex == null) + return result; + else + throw ex; + } + } + }; resolver.setTimeout(LOOKUP_TIMEOUT); Lookup lookup = new Lookup(name, rtype); lookup.setResolver(resolver);