package com.orangelabs.rcs.dns;
import java.net.InetAddress;
import java.net.UnknownHostException;
import javax2.sip.ListeningPoint;
import org.xbill.DNS.Lookup;
import org.xbill.DNS.NAPTRRecord;
import org.xbill.DNS.Record;
import org.xbill.DNS.SRVRecord;
import org.xbill.DNS.TextParseException;
import org.xbill.DNS.Type;
import android.test.AndroidTestCase;
import com.orangelabs.rcs.utils.logger.Logger;
public class DnsTest extends AndroidTestCase {
private Logger logger = Logger.getLogger(this.getClass().getName());
protected void setUp() throws Exception {
super.setUp();
}
protected void tearDown() throws Exception {
super.tearDown();
}
public void testDnsLib() {
String domain = "rcs.lannion.com";
try {
if (logger.isActivated()) {
logger.debug("DNS NAPTR lookup for " + domain);
}
Lookup lookup = new Lookup(domain, Type.NAPTR);
lookup.setCache(null);
Record[] result = lookup.run();
int code = lookup.getResult();
if (code != Lookup.SUCCESSFUL) {
if (logger.isActivated()) {
logger.warn("Lookup error: " + code + "/" + lookup.getErrorString());
}
}
} catch(TextParseException e) {
if (logger.isActivated()) {
logger.debug("Not a valid DNS name");
}
} catch(IllegalArgumentException e) {
if (logger.isActivated()) {
logger.debug("Not a valid DNS type");
}
}
}
public void testDnsResolution() {
resolveImsProxyConfiguration("rcs.lannion.com", ListeningPoint.TCP);
}
private void resolveImsProxyConfiguration(String imsProxyAddr, String imsProxyProtocol) {
int imsProxyPort = -1;
// First try to resolve via a NAPTR query, then a SRV
// query and finally via A query
if (logger.isActivated()) {
logger.debug("Resolve IMS proxy address...");
}
String ipAddress = null;
// DNS NAPTR lookup
String service = null;
if (imsProxyProtocol.equalsIgnoreCase(ListeningPoint.UDP)) {
service = "SIP+D2U";
} else
if (imsProxyProtocol.equalsIgnoreCase(ListeningPoint.TCP)) {
service = "SIP+D2T";
} else
if (imsProxyProtocol.equalsIgnoreCase(ListeningPoint.TLS)) {
service = "SIPS+D2T";
}
Record[] naptrRecords = getDnsNAPTR(imsProxyAddr);
if ((naptrRecords != null) && (naptrRecords.length > 0)) {
if (logger.isActivated()) {
logger.debug("NAPTR records found: " + naptrRecords.length);
}
for (int i = 0; i < naptrRecords.length; i++) {
NAPTRRecord naptr = (NAPTRRecord)naptrRecords[i];
if (logger.isActivated()) {
logger.debug("NAPTR record: " + naptr.toString());
}
if ((naptr != null) && naptr.getService().equalsIgnoreCase(service)) {
// DNS SRV lookup
Record[] srvRecords = getDnsSRV(naptr.getReplacement().toString());
if ((srvRecords != null) && (srvRecords.length > 0)) {
SRVRecord srvRecord = getBestDnsSRV(srvRecords);
ipAddress = getDnsA(srvRecord.getTarget().toString());
imsProxyPort = srvRecord.getPort();
} else {
// Direct DNS A lookup
ipAddress = getDnsA(imsProxyAddr);
}
}
}
} else {
// Direct DNS SRV lookup
if (logger.isActivated()) {
logger.debug("No NAPTR record found: use DNS SRV instead");
}
String query;
if (imsProxyAddr.startsWith("_sip.")) {
query = imsProxyAddr;
} else {
query = "_sip._" + imsProxyProtocol.toLowerCase() + "." + imsProxyAddr;
}
Record[] srvRecords = getDnsSRV(query);
if ((srvRecords != null) && (srvRecords.length > 0)) {
SRVRecord srvRecord = getBestDnsSRV(srvRecords);
ipAddress = getDnsA(srvRecord.getTarget().toString());
imsProxyPort = srvRecord.getPort();
} else {
// Direct DNS A lookup
if (logger.isActivated()) {
logger.debug("No SRV record found: use DNS A instead");
}
ipAddress = getDnsA(imsProxyAddr);
}
}
imsProxyAddr = ipAddress;
if (logger.isActivated()) {
logger.debug("SIP outbound proxy configuration: " +
imsProxyAddr + ":" + imsProxyPort + ";" + imsProxyProtocol);
}
}
private Record[] getDnsNAPTR(String domain) {
try {
if (logger.isActivated()) {
logger.debug("DNS NAPTR lookup for " + domain);
}
Lookup lookup = new Lookup(domain, Type.NAPTR);
lookup.setCache(null);
Record[] result = lookup.run();
int code = lookup.getResult();
if (code != Lookup.SUCCESSFUL) {
if (logger.isActivated()) {
logger.warn("Lookup error: " + code + "/" + lookup.getErrorString());
}
}
return result;
} catch(TextParseException e) {
if (logger.isActivated()) {
logger.debug("Not a valid DNS name");
}
return null;
} catch(IllegalArgumentException e) {
if (logger.isActivated()) {
logger.debug("Not a valid DNS type");
}
return null;
}
}
private Record[] getDnsSRV(String domain) {
try {
if (logger.isActivated()) {
logger.debug("DNS SRV lookup for " + domain);
}
Lookup lookup = new Lookup(domain, Type.SRV);
lookup.setCache(null);
Record[] result = lookup.run();
int code = lookup.getResult();
if (code != Lookup.SUCCESSFUL) {
if (logger.isActivated()) {
logger.warn("Lookup error: " + code + "/" + lookup.getErrorString());
}
}
return result;
} catch(TextParseException e) {
if (logger.isActivated()) {
logger.debug("Not a valid DNS name");
}
return null;
} catch(IllegalArgumentException e) {
if (logger.isActivated()) {
logger.debug("Not a valid DNS type");
}
return null;
}
}
private String getDnsA(String domain) {
try {
if (logger.isActivated()) {
logger.debug("DNS A lookup for " + domain);
}
return InetAddress.getByName(domain).getHostAddress();
} catch(UnknownHostException e) {
if (logger.isActivated()) {
logger.debug("Unknown host for " + domain);
}
return null;
}
}
private SRVRecord getBestDnsSRV(Record[] records) {
SRVRecord result = null;
for (int i = 0; i < records.length; i++) {
SRVRecord srv = (SRVRecord)records[i];
if (logger.isActivated()) {
logger.debug("SRV record: " + srv.toString());
}
if (result == null) {
// First record
result = srv;
} else {
// Next record
if (srv.getPriority() < result.getPriority()) {
// Lowest priority
result = srv;
} else
if (srv.getPriority() == result.getPriority()) {
// Highest weight
if (srv.getWeight() > result.getWeight()) {
result = srv;
}
}
}
}
return result;
}
}