use of org.jivesoftware.smack.util.dns.SRVRecord in project Smack by igniterealtime.
the class DNSUtil method sortSRVRecords.
/**
* Sort a given list of SRVRecords as described in RFC 2782
* Note that we follow the RFC with one exception. In a group of the same priority, only the first entry
* is calculated by random. The others are ore simply ordered by their priority.
*
* @param records
* @return the list of resolved HostAddresses
*/
private static List<HostAddress> sortSRVRecords(List<SRVRecord> records) {
// (the root domain), abort."
if (records.size() == 1 && records.get(0).getFQDN().equals("."))
return Collections.emptyList();
// sorting the records improves the performance of the bisection later
Collections.sort(records);
// create the priority buckets
SortedMap<Integer, List<SRVRecord>> buckets = new TreeMap<Integer, List<SRVRecord>>();
for (SRVRecord r : records) {
Integer priority = r.getPriority();
List<SRVRecord> bucket = buckets.get(priority);
// create the list of SRVRecords if it doesn't exist
if (bucket == null) {
bucket = new LinkedList<SRVRecord>();
buckets.put(priority, bucket);
}
bucket.add(r);
}
List<HostAddress> res = new ArrayList<HostAddress>(records.size());
for (Integer priority : buckets.keySet()) {
List<SRVRecord> bucket = buckets.get(priority);
int bucketSize;
while ((bucketSize = bucket.size()) > 0) {
int[] totals = new int[bucketSize];
int running_total = 0;
int count = 0;
int zeroWeight = 1;
for (SRVRecord r : bucket) {
if (r.getWeight() > 0) {
zeroWeight = 0;
break;
}
}
for (SRVRecord r : bucket) {
running_total += (r.getWeight() + zeroWeight);
totals[count] = running_total;
count++;
}
int selectedPos;
if (running_total == 0) {
// If running total is 0, then all weights in this priority
// group are 0. So we simply select one of the weights randomly
// as the other 'normal' algorithm is unable to handle this case
selectedPos = (int) (Math.random() * bucketSize);
} else {
double rnd = Math.random() * running_total;
selectedPos = bisect(totals, rnd);
}
// add the SRVRecord that was randomly chosen on it's weight
// to the start of the result list
SRVRecord chosenSRVRecord = bucket.remove(selectedPos);
res.add(chosenSRVRecord);
}
}
return res;
}
use of org.jivesoftware.smack.util.dns.SRVRecord in project Smack by igniterealtime.
the class DNSJavaResolver method lookupSRVRecords0.
@Override
protected List<SRVRecord> lookupSRVRecords0(String name, List<HostAddress> failedAddresses, DnssecMode dnssecMode) {
List<SRVRecord> res = new ArrayList<SRVRecord>();
Lookup lookup;
try {
lookup = new Lookup(name, Type.SRV);
} catch (TextParseException e) {
throw new IllegalStateException(e);
}
Record[] recs = lookup.run();
if (recs == null)
return res;
for (Record record : recs) {
org.xbill.DNS.SRVRecord srvRecord = (org.xbill.DNS.SRVRecord) record;
if (srvRecord != null && srvRecord.getTarget() != null) {
String host = srvRecord.getTarget().toString();
int port = srvRecord.getPort();
int priority = srvRecord.getPriority();
int weight = srvRecord.getWeight();
List<InetAddress> hostAddresses = lookupHostAddress0(host, failedAddresses, dnssecMode);
if (hostAddresses == null) {
continue;
}
SRVRecord r = new SRVRecord(host, port, priority, weight, hostAddresses);
res.add(r);
}
}
return res;
}
use of org.jivesoftware.smack.util.dns.SRVRecord in project Smack by igniterealtime.
the class DNSUtil method resolveDomain.
/**
*
* @param domain the domain.
* @param domainType the XMPP domain type, server or client.
* @param failedAddresses a list that will be populated with host addresses that failed to resolve.
* @return a list of resolver host addresses for this domain.
*/
private static List<HostAddress> resolveDomain(String domain, DomainType domainType, List<HostAddress> failedAddresses, DnssecMode dnssecMode) {
if (dnsResolver == null) {
throw new IllegalStateException("No DNS Resolver active in Smack");
}
List<HostAddress> addresses = new ArrayList<HostAddress>();
// Step one: Do SRV lookups
String srvDomain;
switch(domainType) {
case Server:
srvDomain = "_xmpp-server._tcp." + domain;
break;
case Client:
srvDomain = "_xmpp-client._tcp." + domain;
break;
default:
throw new AssertionError();
}
List<SRVRecord> srvRecords = dnsResolver.lookupSRVRecords(srvDomain, failedAddresses, dnssecMode);
if (srvRecords != null && !srvRecords.isEmpty()) {
if (LOGGER.isLoggable(Level.FINE)) {
String logMessage = "Resolved SRV RR for " + srvDomain + ":";
for (SRVRecord r : srvRecords) logMessage += " " + r;
LOGGER.fine(logMessage);
}
List<HostAddress> sortedRecords = sortSRVRecords(srvRecords);
addresses.addAll(sortedRecords);
} else {
LOGGER.info("Could not resolve DNS SRV resource records for " + srvDomain + ". Consider adding those.");
}
int defaultPort = -1;
switch(domainType) {
case Client:
defaultPort = 5222;
break;
case Server:
defaultPort = 5269;
break;
}
// Step two: Add the hostname to the end of the list
HostAddress hostAddress = dnsResolver.lookupHostAddress(domain, defaultPort, failedAddresses, dnssecMode);
if (hostAddress != null) {
addresses.add(hostAddress);
}
return addresses;
}
use of org.jivesoftware.smack.util.dns.SRVRecord in project Smack by igniterealtime.
the class JavaxResolver method lookupSRVRecords0.
@Override
protected List<SRVRecord> lookupSRVRecords0(String name, List<HostAddress> failedAddresses, DnssecMode dnssecMode) {
List<SRVRecord> res = null;
Attribute srvAttribute;
try {
Attributes dnsLookup = dirContext.getAttributes(name, new String[] { "SRV" });
srvAttribute = dnsLookup.get("SRV");
if (srvAttribute == null)
return null;
} catch (NameNotFoundException e) {
LOGGER.log(Level.FINEST, "No DNS SRV RR found for " + name, e);
return null;
} catch (NamingException e) {
LOGGER.log(Level.WARNING, "Exception while resolving DNS SRV RR for " + name, e);
return null;
}
try {
@SuppressWarnings("unchecked") NamingEnumeration<String> srvRecords = (NamingEnumeration<String>) srvAttribute.getAll();
res = new ArrayList<>();
while (srvRecords.hasMore()) {
String srvRecordString = srvRecords.next();
String[] srvRecordEntries = srvRecordString.split(" ");
int priority = Integer.parseInt(srvRecordEntries[srvRecordEntries.length - 4]);
int port = Integer.parseInt(srvRecordEntries[srvRecordEntries.length - 2]);
int weight = Integer.parseInt(srvRecordEntries[srvRecordEntries.length - 3]);
String host = srvRecordEntries[srvRecordEntries.length - 1];
List<InetAddress> hostAddresses = lookupHostAddress0(host, failedAddresses, dnssecMode);
if (hostAddresses == null) {
continue;
}
SRVRecord srvRecord = new SRVRecord(host, port, priority, weight, hostAddresses);
res.add(srvRecord);
}
} catch (NamingException e) {
LOGGER.log(Level.SEVERE, "Exception while resolving DNS SRV RR for" + name, e);
}
return res;
}
use of org.jivesoftware.smack.util.dns.SRVRecord in project Smack by igniterealtime.
the class MiniDnsResolver method lookupSRVRecords0.
@Override
protected List<SRVRecord> lookupSRVRecords0(final String name, List<HostAddress> failedAddresses, DnssecMode dnssecMode) {
final ResolverApi resolver = getResolver(dnssecMode);
ResolverResult<SRV> result;
try {
result = resolver.resolve(name, SRV.class);
} catch (IOException e) {
failedAddresses.add(new HostAddress(name, e));
return null;
}
// TODO: Use ResolverResult.getResolutionUnsuccessfulException() found in newer MiniDNS versions.
if (!result.wasSuccessful()) {
ResolutionUnsuccessfulException resolutionUnsuccessfulException = getExceptionFrom(result);
failedAddresses.add(new HostAddress(name, resolutionUnsuccessfulException));
return null;
}
if (shouldAbortIfNotAuthentic(name, dnssecMode, result, failedAddresses)) {
return null;
}
List<SRVRecord> res = new LinkedList<SRVRecord>();
for (SRV srv : result.getAnswers()) {
String hostname = srv.name.ace;
List<InetAddress> hostAddresses = lookupHostAddress0(hostname, failedAddresses, dnssecMode);
if (hostAddresses == null) {
continue;
}
SRVRecord srvRecord = new SRVRecord(hostname, srv.port, srv.priority, srv.weight, hostAddresses);
res.add(srvRecord);
}
return res;
}
Aggregations