Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Alexander Kuppe2010-07-19 12:15:21 +0000
committerMarkus Alexander Kuppe2010-07-19 12:15:21 +0000
commitdfc694630adf60cd9663bc15f2adca40a232be82 (patch)
treeb0949970a42900a2ed000c1e8d81708d196e258e
parentea1668ebb04ef26cdc5864c8f2d84bbef9943ec3 (diff)
downloadorg.eclipse.ecf-dfc694630adf60cd9663bc15f2adca40a232be82.tar.gz
org.eclipse.ecf-dfc694630adf60cd9663bc15f2adca40a232be82.tar.xz
org.eclipse.ecf-dfc694630adf60cd9663bc15f2adca40a232be82.zip
NEW - bug 320188: [Discovery][DNS-SD] IDiscoveryAdvertiser must use registration domains
https://bugs.eclipse.org/bugs/show_bug.cgi?id=320188
-rw-r--r--providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/DnsSdDiscoveryAdvertiser.java222
-rw-r--r--providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/DnsSdDiscoveryContainerAdapter.java43
-rw-r--r--providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/DnsSdDiscoveryLocator.java5
3 files changed, 188 insertions, 82 deletions
diff --git a/providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/DnsSdDiscoveryAdvertiser.java b/providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/DnsSdDiscoveryAdvertiser.java
index 494bef12e..b416adbc9 100644
--- a/providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/DnsSdDiscoveryAdvertiser.java
+++ b/providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/DnsSdDiscoveryAdvertiser.java
@@ -10,9 +10,14 @@
******************************************************************************/
package org.eclipse.ecf.provider.dnssd;
+import java.io.EOFException;
import java.net.InetAddress;
import java.net.UnknownHostException;
-import java.util.List;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.SortedSet;
import org.eclipse.core.runtime.Assert;
import org.eclipse.ecf.core.ContainerConnectException;
@@ -24,12 +29,14 @@ import org.eclipse.ecf.core.security.IConnectContext;
import org.eclipse.ecf.discovery.DiscoveryContainerConfig;
import org.eclipse.ecf.discovery.IServiceInfo;
import org.eclipse.ecf.discovery.identity.IServiceTypeID;
+import org.xbill.DNS.DClass;
import org.xbill.DNS.Lookup;
import org.xbill.DNS.Message;
import org.xbill.DNS.NSRecord;
import org.xbill.DNS.Name;
import org.xbill.DNS.Rcode;
import org.xbill.DNS.Record;
+import org.xbill.DNS.SOARecord;
import org.xbill.DNS.SRVRecord;
import org.xbill.DNS.SimpleResolver;
import org.xbill.DNS.TextParseException;
@@ -38,6 +45,7 @@ import org.xbill.DNS.Update;
public class DnsSdDiscoveryAdvertiser extends DnsSdDiscoveryContainerAdapter {
+ private static final String _DNS_UPDATE = "_dns-update._udp.";
private static final boolean ADD = true;
private static final boolean REMOVE = false;
@@ -61,6 +69,55 @@ public class DnsSdDiscoveryAdvertiser extends DnsSdDiscoveryContainerAdapter {
sendToServer(serviceInfo, REMOVE);
}
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.discovery.AbstractDiscoveryContainerAdapter#unregisterAllServices()
+ */
+ public void unregisterAllServices() {
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.discovery.AbstractDiscoveryContainerAdapter#purgeCache()
+ */
+ public IServiceInfo[] purgeCache() {
+ // purge cache means renew resolver?
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.provider.dnssd.DnsSdDiscoveryLocator#connect(org.eclipse.ecf.core.identity.ID, org.eclipse.ecf.core.security.IConnectContext)
+ */
+ public void connect(ID aTargetID, IConnectContext connectContext)
+ throws ContainerConnectException {
+
+ // connect can only be called once
+ if (targetID != null || getConfig() == null) {
+ throw new ContainerConnectException("Already connected");
+ }
+
+ //TODO convert non DnsSdServiceTypeIDs into DSTIDs
+ if(aTargetID == null) {
+ targetID = new DnsSdServiceTypeID();
+ } else {
+ targetID = (DnsSdServiceTypeID) aTargetID;
+ }
+
+ // instantiate a default resolver
+ if(resolver == null) {
+ try {
+ resolver = new SimpleResolver();
+ resolver.setTCP(true);
+ } catch (UnknownHostException e) {
+ throw new ContainerConnectException(e);
+ }
+ }
+
+ // done setting up this provider, send event
+ fireContainerEvent(new ContainerConnectingEvent(this.getID(), targetID,
+ connectContext));
+ fireContainerEvent(new ContainerConnectedEvent(this.getID(), targetID));
+ }
+
private void sendToServer(final IServiceInfo serviceInfo, final boolean mode) {
Assert.isNotNull(serviceInfo);
final DnsSdServiceID serviceID = (DnsSdServiceID) serviceInfo.getServiceID();
@@ -93,12 +150,47 @@ public class DnsSdDiscoveryAdvertiser extends DnsSdDiscoveryContainerAdapter {
}
}
- // set up a new resolver for the given domain (a scope might use different domains)
- ((SimpleResolver) resolver).setAddress(getUpdateDomain(zone));
- resolver.setTCP(true);
- final Message response = resolver.send(update);
- if(response.getRcode() != Rcode.NOERROR) {
- throw DnsSdDiscoveryException.getException(response.getRcode());
+ // set up a the resolver for the given domain (a scope might use different domains)
+ final Collection dnsServers = getUpdateDomain(zone);
+ if(dnsServers.size() == 0) {
+ throw new DnsSdDiscoveryException("No server for dnsupdate could be found");
+ }
+ for (final Iterator iterator = dnsServers.iterator(); iterator.hasNext();) {
+ final SRVRecord dnsServer = (SRVRecord) iterator.next();
+
+ // try to send msg and fail gracefully if more dns servers are available
+ final Name target = dnsServer.getTarget();
+ final Message response;
+ final InetAddress byName;
+ try {
+ byName = InetAddress.getByName(target.toString());
+
+ ((SimpleResolver) resolver).setAddress(byName);
+ ((SimpleResolver) resolver).setPort(dnsServer.getPort());
+
+ response = resolver.send(update);
+ } catch (UnknownHostException uhe) {
+ if(iterator.hasNext()) {
+ continue;
+ } else {
+ throw new DnsSdDiscoveryException(uhe);
+ }
+ } catch (EOFException eof) {
+ if(iterator.hasNext()) {
+ continue;
+ } else {
+ throw new DnsSdDiscoveryException(eof);
+ }
+ }
+
+ // catch some errors and fall back to the next dnsServer
+ if (response.getRcode() != Rcode.NOERROR) {
+ if(iterator.hasNext()) {
+ continue;
+ } else {
+ throw DnsSdDiscoveryException.getException(response.getRcode());
+ }
+ }
}
}
} catch (Exception e) {
@@ -106,38 +198,66 @@ public class DnsSdDiscoveryAdvertiser extends DnsSdDiscoveryContainerAdapter {
}
}
- private InetAddress getUpdateDomain(final Name zone) throws TextParseException, UnknownHostException {
- //TODO check if ._udp has to be prepended
- Lookup query = new Lookup("_dns-update._udp." + zone, Type.SRV);
- List srvRecords = getSRVRecord(query);
- if(srvRecords.size() > 0) {
- //TODO use the first one returned for the moment, use prio/weight later
- SRVRecord srvRecord = (SRVRecord) srvRecords.get(0);
- srvRecord.getTarget();
- srvRecord.getPort();
- return null;
+ private Collection getUpdateDomain(final Name zone) throws TextParseException {
+ // query for special "_dns-update" SRV records which mark the server to use for dyndns
+ final Lookup query = new Lookup(_DNS_UPDATE + zone, Type.SRV);
+ // use the SRV record with the lowest priority/weight first
+ final SortedSet srvRecords = getSRVRecord(query, new SRVRecordComparator());
+//
+// int prio = Integer.MAX_VALUE, weight = Integer.MAX_VALUE;
+// for (Iterator iterator = srvRecords.iterator(); iterator.hasNext();) {
+// final SRVRecord srvRecord = (SRVRecord) iterator.next();
+// if(srvRecord.getPriority() < prio) {
+// if (srvRecord.getWeight() < weight) {
+// prio = srvRecord.getPriority();
+// weight = srvRecord.getPriority();
+// result.add(new URI("dns://" + srvRecord.getTarget() + ":" + srvRecord.getPort()));
+// }
+// }
+// }
+
+ // if no dedicated "_dns-update" server is configured, fall back to regular authoritative server
+ if(srvRecords.size() == 0) {
+ return getAuthoritativeNameServer(zone);
}
- return getAuthoritiveNameServer(zone);
+ return srvRecords;
}
- private InetAddress getAuthoritiveNameServer(final Name zone) throws UnknownHostException {
- final Lookup query = new Lookup(zone, Type.NS);
+ private Collection getAuthoritativeNameServer(final Name zone) throws TextParseException {
+ final Set result = new HashSet();
+ final Name name = new Name(_DNS_UPDATE + zone);
+
+ //query for NS records
+ Lookup query = new Lookup(zone, Type.NS);
query.setResolver(resolver);
- final Record[] queryResult = query.run();
+ Record[] queryResult = query.run();
//TODO file bug upstream that queryResult may never be null
int length = queryResult == null ? 0 : queryResult.length;
for (int j = 0; j < length; j++) {
- Record record = queryResult[j];
+ final Record record = queryResult[j];
if(record instanceof NSRecord) {
- NSRecord nsRecord = (NSRecord) record;
- Name target = nsRecord.getTarget();
- return InetAddress.getByName(target.toString());
+ final NSRecord nsRecord = (NSRecord) record;
+ final Name target = nsRecord.getTarget();
+ result.add(new SRVRecord(name, DClass.IN, nsRecord.getTTL(), 0, 0, SimpleResolver.DEFAULT_PORT, target));
}
}
- return null;
+
+ //query for primary ns in SOA record (may overwrite/be equal to one of the ns records)
+ query = new Lookup(zone, Type.SOA);
+ query.setResolver(resolver);
+ queryResult = query.run();
+ //TODO file bug upstream that queryResult may never be null
+ length = queryResult == null ? 0 : queryResult.length;
+ for (int j = 0; j < length; j++) {
+ final Record record = queryResult[j];
+ if(record instanceof SOARecord) {
+ final SOARecord soaRecord = (SOARecord) record;
+ result.add(new SRVRecord(name, DClass.IN, soaRecord.getTTL(), 0, 0, SimpleResolver.DEFAULT_PORT, soaRecord.getHost()));
+ }
+ }
+ return result;
}
-
private String[] getRegistrationDomains(IServiceTypeID aServiceTypeId) {
String[] rrs = new String[] {BnRDnsSdServiceTypeID.REG_DOMAINS, BnRDnsSdServiceTypeID.DEFAULT_REG_DOMAIN};
final String[] registrationDomains = getBrowsingOrRegistrationDomains(aServiceTypeId, rrs);
@@ -147,52 +267,4 @@ public class DnsSdDiscoveryAdvertiser extends DnsSdDiscoveryContainerAdapter {
}
return registrationDomains.length == 0 ? scopes : registrationDomains;
}
-
- /* (non-Javadoc)
- * @see org.eclipse.ecf.discovery.AbstractDiscoveryContainerAdapter#unregisterAllServices()
- */
- public void unregisterAllServices() {
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.ecf.discovery.AbstractDiscoveryContainerAdapter#purgeCache()
- */
- public IServiceInfo[] purgeCache() {
- // purge cache means renew resolver?
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.ecf.provider.dnssd.DnsSdDiscoveryLocator#connect(org.eclipse.ecf.core.identity.ID, org.eclipse.ecf.core.security.IConnectContext)
- */
- public void connect(ID aTargetID, IConnectContext connectContext)
- throws ContainerConnectException {
-
- // connect can only be called once
- if (targetID != null || getConfig() == null) {
- throw new ContainerConnectException("Already connected");
- }
-
- //TODO convert non DnsSdServiceTypeIDs into DSTIDs
- if(aTargetID == null) {
- targetID = new DnsSdServiceTypeID();
- } else {
- targetID = (DnsSdServiceTypeID) aTargetID;
- }
-
- // instantiate a default resolver
- if(resolver == null) {
- try {
- resolver = new SimpleResolver();
- } catch (UnknownHostException e) {
- throw new ContainerConnectException(e);
- }
- }
-
- // done setting up this provider, send event
- fireContainerEvent(new ContainerConnectingEvent(this.getID(), targetID,
- connectContext));
- fireContainerEvent(new ContainerConnectedEvent(this.getID(), targetID));
- }
}
diff --git a/providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/DnsSdDiscoveryContainerAdapter.java b/providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/DnsSdDiscoveryContainerAdapter.java
index 00b489c88..d9c8853e6 100644
--- a/providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/DnsSdDiscoveryContainerAdapter.java
+++ b/providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/DnsSdDiscoveryContainerAdapter.java
@@ -13,9 +13,12 @@ package org.eclipse.ecf.provider.dnssd;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
import org.eclipse.core.runtime.Assert;
import org.eclipse.ecf.core.ContainerConnectException;
@@ -167,16 +170,20 @@ public abstract class DnsSdDiscoveryContainerAdapter extends
return (Record[]) result.toArray(new Record[result.size()]);
}
- protected List getSRVRecords(Lookup[] queries) {
- List srvRecords = new ArrayList();
+ protected SortedSet getSRVRecords(Lookup[] queries) {
+ return getSRVRecords(queries, null);
+ }
+
+ protected SortedSet getSRVRecords(Lookup[] queries, Comparator aComparator) {
+ final SortedSet srvRecords = new TreeSet(aComparator);
for (int i = 0; i < queries.length; i++) {
- srvRecords.addAll(getSRVRecord(queries[i]));
+ srvRecords.addAll(getSRVRecord(queries[i], aComparator));
}
return srvRecords;
}
- protected List getSRVRecord(Lookup query) {
- final List srvRecords = new ArrayList();
+ protected SortedSet getSRVRecord(Lookup query, Comparator aComparator) {
+ final SortedSet srvRecords = new TreeSet(aComparator);
query.setResolver(resolver);
final Record[] queryResult = query.run();
//TODO file bug upstream that queryResult may never be null
@@ -198,6 +205,32 @@ public abstract class DnsSdDiscoveryContainerAdapter extends
return srvRecords;
}
+ // compares SRV records based on priority and weight
+ protected class SRVRecordComparator implements Comparator {
+
+ /* (non-Javadoc)
+ * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
+ */
+ public int compare(Object arg0, Object arg1) {
+ if(arg0 instanceof SRVRecord && arg1 instanceof SRVRecord) {
+ SRVRecord srv1 = (SRVRecord) arg0;
+ SRVRecord srv2 = (SRVRecord) arg1;
+ if(srv1.getPriority() > srv2.getPriority()) {
+ return 1;
+ } else if (srv1.getPriority() == srv2.getPriority()) {
+ if(srv1.getWeight() > srv2.getWeight()) {
+ return 1;
+ }
+ return -1;
+ } else {
+ return -1;
+ }
+ }
+ throw new UnsupportedOperationException("This appears to be a bug: Comparator can only compare SRVRecords");
+ }
+
+ }
+
/**
* @param searchPaths The default search path used for discovery
*/
diff --git a/providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/DnsSdDiscoveryLocator.java b/providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/DnsSdDiscoveryLocator.java
index 691aa3456..ddc96392c 100644
--- a/providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/DnsSdDiscoveryLocator.java
+++ b/providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/DnsSdDiscoveryLocator.java
@@ -13,6 +13,7 @@ package org.eclipse.ecf.provider.dnssd;
import java.net.URI;
import java.net.UnknownHostException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
@@ -119,12 +120,12 @@ public class DnsSdDiscoveryLocator extends DnsSdDiscoveryContainerAdapter {
public IServiceInfo[] getServices(IServiceTypeID aServiceTypeId) {
Assert.isNotNull(aServiceTypeId);
DnsSdServiceTypeID serviceTypeId = (DnsSdServiceTypeID) aServiceTypeId;
- List srvRecords = getSRVRecords(serviceTypeId.getInternalQueries());
+ Collection srvRecords = getSRVRecords(serviceTypeId.getInternalQueries());
List serviceInfos = getServiceInfos(srvRecords);
return (IServiceInfo[]) serviceInfos.toArray(new IServiceInfo[serviceInfos.size()]);
}
- private List getServiceInfos(List srvQueryResult) {
+ private List getServiceInfos(Collection srvQueryResult) {
List infos = new ArrayList();
for (Iterator iterator = srvQueryResult.iterator(); iterator.hasNext();) {
SRVRecord srvRecord = (SRVRecord) iterator.next();

Back to the top