use of org.minidns.record.SRV in project minidns by MiniDNS.
the class SrvUtil method sortSrvRecords.
/**
* Sort the given collection of {@link SRV} resource records by their priority and weight.
* <p>
* Sorting by priority is easy. Sorting the buckets of SRV records with the same priority by weight requires to choose those records
* randomly but taking the weight into account.
* </p>
*
* @param srvRecords
* a collection of SRV records.
* @return a sorted list of the given records.
*/
public static List<SRV> sortSrvRecords(Collection<SRV> srvRecords) {
// (the root domain), abort."
if (srvRecords.size() == 1 && srvRecords.iterator().next().target.equals(DNSName.ROOT)) {
return Collections.emptyList();
}
// Create the priority buckets.
SortedMap<Integer, List<SRV>> buckets = new TreeMap<>();
for (SRV srvRecord : srvRecords) {
Integer priority = srvRecord.priority;
List<SRV> bucket = buckets.get(priority);
if (bucket == null) {
bucket = new LinkedList<>();
buckets.put(priority, bucket);
}
bucket.add(srvRecord);
}
List<SRV> sortedSrvRecords = new ArrayList<>(srvRecords.size());
for (List<SRV> bucket : buckets.values()) {
// The list of buckets will be sorted by priority, thanks to SortedMap. We now have determine the order of
// the SRV records with the same priority, i.e., within the same bucket, by their weight. This is done by
// creating an array 'totals' which reflects the percentage of the SRV RRs weight by the total weight of all
// SRV RRs in the bucket. For every entry in the bucket, we choose one using a random number and the sum of
// all weights left in the bucket. We then select RRs position based on the according index of the selected
// value in the 'total' array. This ensures that its weight is taken into account.
int bucketSize;
while ((bucketSize = bucket.size()) > 0) {
int[] totals = new int[bucketSize];
int zeroWeight = 1;
for (SRV srv : bucket) {
if (srv.weight > 0) {
zeroWeight = 0;
break;
}
}
int bucketWeightSum = 0, count = 0;
for (SRV srv : bucket) {
bucketWeightSum += (srv.weight + zeroWeight);
totals[count++] = bucketWeightSum;
}
int selectedPosition;
if (bucketWeightSum == 0) {
// If total priority is 0, then the sum of all weights in this priority bucket is 0. So we simply
// select one of the weights randomly as the other algorithm performed in the else block is unable
// to handle this case.
selectedPosition = (int) (Math.random() * bucketSize);
} else {
double rnd = Math.random() * bucketWeightSum;
selectedPosition = bisect(totals, rnd);
}
SRV choosenSrvRecord = bucket.remove(selectedPosition);
sortedSrvRecords.add(choosenSrvRecord);
}
}
return sortedSrvRecords;
}
use of org.minidns.record.SRV in project minidns by MiniDNS.
the class SrvUtilTest method createSRVRecords.
private static List<SRV> createSRVRecords() {
List<SRV> records = new ArrayList<>();
// We create one record with priority 0 that should also be tried first
// Then 4 records with priority 5 and different weights (50, 20, 20, 10)
// Then 2 records with priority 10 and weight 0 which should be treated equal
// These records are added in a 'random' way to the list
// Priority 5, Weight 20
records.add(new SRV(5, 20, 42, "5.20.one.foo.bar"));
// Priority 10, Weight 0
records.add(new SRV(10, 0, 42, "10.0.one.foo.bar"));
// Priority 5, Weight 10
records.add(new SRV(5, 10, 42, "5.10.foo.bar"));
// Priority 10, Weight 0
records.add(new SRV(10, 0, 42, "10.0.two.foo.bar"));
// Priority 5, Weight 20
records.add(new SRV(5, 20, 42, "5.20.two.foo.bar"));
// Priority 0, Weight 20
records.add(new SRV(0, 20, 42, "0.20.foo.bar"));
// Priority 5, Weight 50
records.add(new SRV(5, 50, 42, "5.50.foo.bar"));
return records;
}
use of org.minidns.record.SRV in project minidns by MiniDNS.
the class HlaTest method idnSrvTest.
@IntegrationTest
public static void idnSrvTest() throws IOException {
ResolverResult<SRV> res = ResolverApi.INSTANCE.resolve("_xmpp-client._tcp.im.plä.net", SRV.class);
Set<SRV> answers = res.getAnswers();
assertEquals(1, answers.size());
SRV srv = answers.iterator().next();
ResolverResult<A> aRes = ResolverApi.INSTANCE.resolve(srv.target, A.class);
assertTrue(aRes.wasSuccessful());
}
use of org.minidns.record.SRV in project minidns by MiniDNS.
the class DNSMessageTest method testSRVLookup.
@Test
public void testSRVLookup() throws Exception {
DNSMessage m = getMessageFromResource("gpn-srv");
assertFalse(m.authoritativeAnswer);
List<Record<? extends Data>> answers = m.answerSection;
assertEquals(1, answers.size());
Record<? extends Data> answer = answers.get(0);
assertTrue(answer.getPayload() instanceof SRV);
assertEquals(TYPE.SRV, answer.getPayload().getType());
SRV r = (SRV) (answer.getPayload());
assertCsEquals("raven.toroid.org", r.target);
assertEquals(5222, r.port);
assertEquals(0, r.priority);
}
use of org.minidns.record.SRV in project minidns by MiniDNS.
the class SrvResolverResult method getSortedSrvResolvedAddresses.
public List<ResolvedSrvRecord> getSortedSrvResolvedAddresses() throws IOException {
if (sortedSrvResolvedAddresses != null) {
return sortedSrvResolvedAddresses;
}
throwIseIfErrorResponse();
List<SRV> srvRecords = SrvUtil.sortSrvRecords(getAnswers());
List<ResolvedSrvRecord> res = new ArrayList<>(srvRecords.size());
for (SRV srvRecord : srvRecords) {
ResolverResult<A> aRecordsResult = null;
ResolverResult<AAAA> aaaaRecordsResult = null;
Set<A> aRecords = Collections.emptySet();
if (ipVersion.v4) {
aRecordsResult = resolver.resolve(srvRecord.target, A.class);
if (aRecordsResult.wasSuccessful() && !aRecordsResult.hasUnverifiedReasons()) {
aRecords = aRecordsResult.getAnswers();
}
}
Set<AAAA> aaaaRecords = Collections.emptySet();
if (ipVersion.v6) {
aaaaRecordsResult = resolver.resolve(srvRecord.target, AAAA.class);
if (aaaaRecordsResult.wasSuccessful() && !aaaaRecordsResult.hasUnverifiedReasons()) {
aaaaRecords = aaaaRecordsResult.getAnswers();
}
}
if (aRecords.isEmpty() && aaaaRecords.isEmpty()) {
/*
ResolverResult<CNAME> cnameRecordResult = resolve(srvRecord.name, CNAME.class);
if (cnameRecordResult.wasSuccessful()) {
}
*/
continue;
}
List<InternetAddressRR> srvAddresses = new ArrayList<>(aRecords.size() + aaaaRecords.size());
switch(ipVersion) {
case v4only:
for (A a : aRecords) {
srvAddresses.add(a);
}
break;
case v6only:
for (AAAA aaaa : aaaaRecords) {
srvAddresses.add(aaaa);
}
break;
case v4v6:
for (A a : aRecords) {
srvAddresses.add(a);
}
for (AAAA aaaa : aaaaRecords) {
srvAddresses.add(aaaa);
}
break;
case v6v4:
for (AAAA aaaa : aaaaRecords) {
srvAddresses.add(aaaa);
}
for (A a : aRecords) {
srvAddresses.add(a);
}
break;
}
ResolvedSrvRecord resolvedSrvAddresses = new ResolvedSrvRecord(question.name, srvRecord, srvAddresses, aRecordsResult, aaaaRecordsResult);
res.add(resolvedSrvAddresses);
}
sortedSrvResolvedAddresses = res;
return res;
}
Aggregations