Skip to content

Instantly share code, notes, and snippets.

@ericcj
Created February 28, 2017 17:10
Show Gist options
  • Save ericcj/a4e5c99982d36d3348ff3c732fa51038 to your computer and use it in GitHub Desktop.
Save ericcj/a4e5c99982d36d3348ff3c732fa51038 to your computer and use it in GitHub Desktop.
Naive timeout for DNS resolution using a thread per request
/**
* Based on http://stackoverflow.com/questions/693997/how-to-set-httpresponse-timeout-for-android-in-java/31643186#31643186
* as per https://github.com/square/okhttp/issues/95
*/
private static class DNSTimeoutInterceptor implements Interceptor {
long mTimeoutMillis;
public DNSTimeoutInterceptor(long timeoutMillis) {
mTimeoutMillis = timeoutMillis;
}
@Override
public Response intercept(final Chain chain) throws IOException {
Request request = chain.request();
Log.SplitTimer timer = (request.tag() instanceof RequestTag ? ((RequestTag) request.tag()).getTimer() : null);
// underlying call should timeout after 2 tries of 5s: https://android.googlesource.com/platform/bionic/+/android-5.1.1_r38/libc/dns/include/resolv_private.h#137
// could use our own Dns implementation that falls back to public DNS servers: https://garage.easytaxi.com/tag/dns-android-okhttp/
if (!DNSResolver.isDNSReachable(request.url().host(), mTimeoutMillis)) {
throw new UnknownHostException("DNS timeout");
}
return chain.proceed(request);
}
private static class DNSResolver implements Runnable {
private String mDomain;
private InetAddress mAddress;
public static boolean isDNSReachable(String domain, long timeoutMillis) {
try {
DNSResolver dnsRes = new DNSResolver(domain);
Thread t = new Thread(dnsRes, "DNSResolver");
t.start();
t.join(timeoutMillis);
return dnsRes.get() != null;
} catch(Exception e) {
return false;
}
}
public DNSResolver(String domain) {
this.mDomain = domain;
}
public void run() {
try {
InetAddress addr = InetAddress.getByName(mDomain);
set(addr);
} catch (UnknownHostException e) {
}
}
public synchronized void set(InetAddress inetAddr) {
this.mAddress = inetAddr;
}
public synchronized InetAddress get() {
return mAddress;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment