diff options
| author | Markus Alexander Kuppe | 2010-06-10 09:42:52 +0000 |
|---|---|---|
| committer | Markus Alexander Kuppe | 2010-06-10 09:42:52 +0000 |
| commit | 492b00ab1ec907a83a32a7cace0375057cea7c84 (patch) | |
| tree | 01444e27c7472a51c2105fb0d711cdd509e851dd | |
| parent | cebbdc4110d6f558d41fb6001c93658bf8702967 (diff) | |
| download | org.eclipse.ecf-492b00ab1ec907a83a32a7cace0375057cea7c84.tar.gz org.eclipse.ecf-492b00ab1ec907a83a32a7cace0375057cea7c84.tar.xz org.eclipse.ecf-492b00ab1ec907a83a32a7cace0375057cea7c84.zip | |
NEW - bug 315970: [Discovery][DNS-SD] Discovery of Browsing and Registration Domains (Domain Enumeration)
https://bugs.eclipse.org/bugs/show_bug.cgi?id=315970
4 files changed, 172 insertions, 48 deletions
diff --git a/providers/bundles/org.eclipse.ecf.provider.dnssd/.gitignore b/providers/bundles/org.eclipse.ecf.provider.dnssd/.gitignore new file mode 100644 index 000000000..6dd29b7f8 --- /dev/null +++ b/providers/bundles/org.eclipse.ecf.provider.dnssd/.gitignore @@ -0,0 +1 @@ +bin/
\ No newline at end of file diff --git a/providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/BnRDnsSdServiceTypeID.java b/providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/BnRDnsSdServiceTypeID.java new file mode 100644 index 000000000..4a8cb3d6e --- /dev/null +++ b/providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/BnRDnsSdServiceTypeID.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2010 Markus Alexander Kuppe. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Alexander Kuppe (ecf-dev_eclipse.org <at> lemmster <dot> de) - initial API and implementation + ******************************************************************************/ +package org.eclipse.ecf.provider.dnssd; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.ecf.discovery.identity.IServiceTypeID; +import org.xbill.DNS.Lookup; +import org.xbill.DNS.TextParseException; +import org.xbill.DNS.Type; + +/** + * This ServiceType represents the special RRs defined in + * chapter 12. Discovery of Browsing and Registration Domains + * + * @see http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt + */ +public class BnRDnsSdServiceTypeID extends DnsSdServiceTypeID { + private static final long serialVersionUID = -466458565598238072L; + + /** + * A list of domains recommended for browsing + */ + static final String BROWSE_DOMAIN = "b._dns-sd"; + /** + * A single recommended default domain for browsing + */ + static final String DEFAULT_BROWSE_DOMAIN = "db._dns-sd"; + /** + * A list of domains recommended for registering services using Dynamic Update + */ + static final String REG_DOMAIN = "r._dns-sd"; + /** + * A single recommended default domain for registering services. + */ + static final String DEFAULT_REG_DOMAIN = "dr._dns-sd"; + + BnRDnsSdServiceTypeID(IServiceTypeID aServiceType, String aService) { + super(aServiceType.getNamespace(), aServiceType); + services = new String[] {aService}; + } + + /* (non-Javadoc) + * @see org.eclipse.ecf.provider.dnssd.DnsSdServiceTypeID#getInternalQueries() + */ + Lookup[] getInternalQueries() { + List result = new ArrayList(); + for (int i = 0; i < scopes.length; i++) { + String scope = scopes[i]; + // remove dangling "." + if(scope.endsWith(".")) { + scope = scope.substring(0, scope.length() - 1); + } + Lookup query; + try { + query = new Lookup(services[0] + "._udp" + "." + scope + ".", + Type.PTR); + } catch (TextParseException e) { + continue; + } + result.add(query); + } + return (Lookup[]) result.toArray(new Lookup[result.size()]); + } +} diff --git a/providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/DnsSdDisocoveryLocator.java b/providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/DnsSdDisocoveryLocator.java index 69e78b0f8..bb4a3e07c 100644 --- a/providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/DnsSdDisocoveryLocator.java +++ b/providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/DnsSdDisocoveryLocator.java @@ -14,9 +14,11 @@ import java.net.URI; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Properties; +import java.util.Set; import org.eclipse.core.runtime.Assert; import org.eclipse.ecf.core.ContainerConnectException; @@ -86,27 +88,38 @@ public class DnsSdDisocoveryLocator extends AbstractDiscoveryContainerAdapter { */ public IServiceTypeID[] getServiceTypes() { // technically can't do anything without a scope (domain) -> falling back to local domain (mDNS?) - List result = new ArrayList(); DnsSdServiceTypeID serviceTypeId = (DnsSdServiceTypeID) targetID; + return getServiceTypes(serviceTypeId); + } + + private IServiceTypeID[] getServiceTypes(final DnsSdServiceTypeID serviceTypeId) { + List result = new ArrayList(); + Record[] queryResult = getRecords(serviceTypeId); + for (int j = 0; j < queryResult.length; j++) { + Record record = queryResult[j]; + if(record instanceof PTRRecord) { + PTRRecord ptrRecord = (PTRRecord) record; + result.add(new DnsSdServiceTypeID(getServicesNamespace(), ptrRecord.getTarget())); + } else if (record instanceof SRVRecord) { + SRVRecord srvRecord = (SRVRecord) record; + result.add(new DnsSdServiceTypeID(getServicesNamespace(), srvRecord.getName())); + } + } + return (IServiceTypeID[]) result.toArray(new IServiceTypeID[result.size()]); + } + + private Record[] getRecords(final DnsSdServiceTypeID serviceTypeId) { + List result = new ArrayList(); Lookup[] queries = serviceTypeId.getInternalQueries(); for (int i = 0; i < queries.length; i++) { Lookup query = queries[i]; query.setResolver(resolver); 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]; - if(record instanceof PTRRecord) { - PTRRecord ptrRecord = (PTRRecord) record; - result.add(new DnsSdServiceTypeID(getServicesNamespace(), ptrRecord.getTarget())); - } else if (record instanceof SRVRecord) { - SRVRecord srvRecord = (SRVRecord) record; - result.add(new DnsSdServiceTypeID(getServicesNamespace(), srvRecord.getName())); - } + if(queryResult != null) { + result.addAll(Arrays.asList(queryResult)); } } - return (IServiceTypeID[]) result.toArray(new IServiceTypeID[result.size()]); + return (Record[]) result.toArray(new Record[result.size()]); } /* @@ -236,32 +249,60 @@ public class DnsSdDisocoveryLocator extends AbstractDiscoveryContainerAdapter { */ 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"); } + + // fall back to the search path as last resort if(aTargetID == null || !(aTargetID instanceof DnsSdServiceTypeID)) { - // fall back to the search path as last resort ResolverConfig config = new ResolverConfig(); Name[] searchPaths = config.searchPath(); if(searchPaths.length >= 0) { targetID = new DnsSdServiceTypeID(); - targetID.setScopes(searchPaths); + targetID.setSearchPath(searchPaths); } else { throw new ContainerConnectException("No target id given"); } } else { targetID = (DnsSdServiceTypeID) aTargetID; } + + // instantiate a default resolver try { resolver = new SimpleResolver(); } catch (UnknownHostException e) { throw new ContainerConnectException(e); } - fireContainerEvent(new ContainerConnectingEvent(this.getID(), targetID, + + // read browsing domains for the given targetID/searchpath and merge with existing + targetID.addSearchPath(getBrowsingDomains(targetID)); + + // done setting up this provider, send event + fireContainerEvent(new ContainerConnectingEvent(this.getID(), targetID, connectContext)); fireContainerEvent(new ContainerConnectedEvent(this.getID(), targetID)); } + private String[] getBrowsingDomains(IServiceTypeID aServiceTypeId) { + Set res = new HashSet(); + + String[] rrs = new String[] {BnRDnsSdServiceTypeID.BROWSE_DOMAIN, BnRDnsSdServiceTypeID.DEFAULT_BROWSE_DOMAIN}; + for (int i = 0; i < rrs.length; i++) { + BnRDnsSdServiceTypeID serviceType = + new BnRDnsSdServiceTypeID(aServiceTypeId, rrs[i]); + + Record[] defaultBrowsing = getRecords(serviceType); + for (int j = 0; j < defaultBrowsing.length; j++) { + PTRRecord record = (PTRRecord) defaultBrowsing[j]; + res.add(record.getTarget().toString()); + } + } + + return (String[]) res.toArray(new String[res.size()]); + } + /* * (non-Javadoc) * @@ -288,7 +329,7 @@ public class DnsSdDisocoveryLocator extends AbstractDiscoveryContainerAdapter { * @param searchPaths The default search path used for discovery */ public void setSearchPath(String[] searchPaths) { - targetID.setScopes(searchPaths); + targetID.setSearchPath(searchPaths); } /** diff --git a/providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/DnsSdServiceTypeID.java b/providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/DnsSdServiceTypeID.java index 4db8e2527..1ae3ad1c7 100644 --- a/providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/DnsSdServiceTypeID.java +++ b/providers/bundles/org.eclipse.ecf.provider.dnssd/src/org/eclipse/ecf/provider/dnssd/DnsSdServiceTypeID.java @@ -10,10 +10,12 @@ ******************************************************************************/ package org.eclipse.ecf.provider.dnssd; -import java.net.InetAddress; -import java.net.UnknownHostException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.eclipse.ecf.core.identity.IDCreateException; import org.eclipse.ecf.core.identity.Namespace; @@ -27,6 +29,14 @@ import org.xbill.DNS.Type; public class DnsSdServiceTypeID extends ServiceTypeID implements IServiceTypeID { private static final long serialVersionUID = 1247933069737880365L; + + DnsSdServiceTypeID() { + super(new DnsSdNamespace()); + scopes = DEFAULT_SCOPE; + protocols = DEFAULT_PROTO; + namingAuthority = DEFAULT_NA; + services = new String[]{""}; + } public DnsSdServiceTypeID(Namespace ns, IServiceTypeID id) { super(ns, id); @@ -36,32 +46,7 @@ public class DnsSdServiceTypeID extends ServiceTypeID implements IServiceTypeID throws IDCreateException { super(namespace, aType); } - - public DnsSdServiceTypeID(Namespace namespace, String[] services, - String[] scopes, String[] protocols, String namingAuthority) { - super(namespace, services, scopes, protocols, namingAuthority); - } - - public DnsSdServiceTypeID(Namespace namespace) { - super(namespace); - try { - final InetAddress localHost = InetAddress.getLocalHost(); - final String fqdn = localHost.getCanonicalHostName(); - int idx = fqdn.indexOf("."); - if(idx > -1) { - scopes = new String[]{fqdn.substring(idx +1)}; - } else { - scopes = new String[]{fqdn}; - } - } catch (UnknownHostException e) { - scopes = null; - } - } - DnsSdServiceTypeID() { - super(new DnsSdNamespace()); - } - DnsSdServiceTypeID(Namespace namespace, Name aName) { super(namespace, aName.toString()); } @@ -110,22 +95,45 @@ public class DnsSdServiceTypeID extends ServiceTypeID implements IServiceTypeID return (Lookup[]) result.toArray(new Lookup[result.size()]); } - public void setScopes(Name[] searchPaths) { + /** + * @param searchPaths Sets the default search path + */ + void setSearchPath(Name[] searchPaths) { String[] s = new String[searchPaths.length]; for(int i = 0; i < searchPaths.length; i++) { s[i] = searchPaths[i].toString(); } - setScopes(s); + setSearchPath(s); } - public void setScopes(String[] searchPaths) { + /** + * @param searchPaths Sets the default search path + */ + void setSearchPath(String[] searchPaths) { scopes = searchPaths; } /** * @return Search scopes used during discovery */ - public String[] getSearchPath() { + String[] getSearchPath() { return scopes; } + + /** + * @param additionalSearchPaths Adds the given array to the existing search paths + */ + void addSearchPath(String[] additionalSearchPaths) { + //convert arrays to collections (lists) + Collection coll1 = Arrays.asList(scopes); + Collection coll2 = Arrays.asList(additionalSearchPaths); + + // remove dupes + Set s = new HashSet(); + s.addAll(coll1); + s.addAll(coll2); + + // convert into new scopes + scopes = (String[]) s.toArray(new String[s.size()]); + } } |
