package com.buddycloud.utils; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.xbill.DNS.Lookup; import org.xbill.DNS.Record; import org.xbill.DNS.TXTRecord; import org.xbill.DNS.TextParseException; import org.xbill.DNS.Type; import android.os.AsyncTask; import com.buddycloud.model.ModelCallback; public class DNSUtils { private static final String TXT_PREFIX = "_buddycloud-api._tcp."; /** * Adapted from https://code.google.com/p/asmack/source/browse/src/custom/org/jivesoftware/smack/util/DNSUtil.java * * @param domain * @return * @throws TextParseException */ @SuppressWarnings("unchecked") private static String resolveAPITXT(String domain) throws TextParseException { Lookup lookup = new Lookup(TXT_PREFIX + domain, Type.TXT); Record recs[] = lookup.run(); if (recs == null) { throw new RuntimeException("Could not lookup domain."); } Map<String, String> stringMap = null; for (Record rec : recs) { String rData = rec.rdataToString().replaceAll("\"", ""); List<String> rDataTokens = Arrays.asList(rData.split("\\s+")); TXTRecord record = new TXTRecord(rec.getName(), rec.getDClass(), rec.getTTL(), rDataTokens); List<String> strings = record.getStrings(); if (strings != null && strings.size() > 0) { stringMap = parseStrings(strings); break; } } if (stringMap == null) { throw new RuntimeException("Domain has no TXT records for buddycloud."); } String host = stringMap.get("host"); String protocol = stringMap.get("protocol"); String path = stringMap.get("path"); String port = stringMap.get("port"); path = path == null || path.equals("/") ? "" : path; port = port == null ? "" : port; return protocol + "://" + host + ":" + port + path; } private static Map<String, String> parseStrings(List<String> rDataTokens) { Map<String, String> stringsMap = new HashMap<String, String>(); for (String rToken : rDataTokens) { String[] splitToken = rToken.trim().split("="); stringsMap.put(splitToken[0], splitToken[1]); } return stringsMap; } public static void resolveAPISRV(final ModelCallback<String> apiAddressCallback, final String domain) { new AsyncTask<Void, Void, String>() { private Throwable e; @Override protected String doInBackground(Void... params) { try { return resolveAPITXT(domain); } catch (Throwable e) { this.e = e; return null; } } @Override protected void onPostExecute(String result) { if (e != null) { apiAddressCallback.error(e); } else { apiAddressCallback.success(result); } } }.execute(); } }