Support for International Domain Names in DNSUtil

This commit is contained in:
Florian Schmaus 2014-09-13 09:27:55 +02:00
parent f2718c2d76
commit d3cea48c0d
2 changed files with 78 additions and 9 deletions

View File

@ -39,6 +39,23 @@ public class DNSUtil {
private static final Logger LOGGER = Logger.getLogger(DNSUtil.class.getName());
private static DNSResolver dnsResolver = null;
/**
* International Domain Name transformer.
* <p>
* Used to transform Unicode representations of the Domain Name to ASCII in
* order to perform a DNS request with the ASCII representation.
* 'java.net.IDN' is available since Android API 9, but as long as Smack
* requires API 8, we are going to need this. This part is going to get
* removed once Smack depends on Android API 9 or higher.
* </p>
*/
private static StringTransformer idnaTransformer = new StringTransformer() {
@Override
public String transform(String string) {
return string;
}
};
/**
* Set the DNS resolver that should be used to perform DNS lookups.
*
@ -57,6 +74,27 @@ public class DNSUtil {
return dnsResolver;
}
/**
* Set the IDNA (Internatiionalizing Domain Names in Applications, RFC 3490) transformer.
* <p>
* You usually want to wrap 'java.net.IDN.toASCII()' into a StringTransformer here.
* </p>
* @param idnaTransformer
*/
public static void setIdnaTransformer(StringTransformer idnaTransformer) {
if (idnaTransformer == null) {
throw new NullPointerException();
}
DNSUtil.idnaTransformer = idnaTransformer;
}
private static enum DomainType {
Server,
Client,
;
}
/**
* Returns a list of HostAddresses under which the specified XMPP server can be
* reached at for client-to-server communication. A DNS lookup for a SRV
@ -75,13 +113,15 @@ public class DNSUtil {
* XMPP server can be reached at for the specified domain.
* @throws Exception
*/
public static List<HostAddress> resolveXMPPDomain(final String domain) throws Exception {
public static List<HostAddress> resolveXMPPDomain(String domain) throws Exception {
domain = idnaTransformer.transform(domain);
if (dnsResolver == null) {
LOGGER.warning("No DNS Resolver active in Smack, will be unable to perform DNS SRV lookups");
List<HostAddress> addresses = new ArrayList<HostAddress>(1);
addresses.add(new HostAddress(domain, 5222));
return addresses;
}
return resolveDomain(domain, 'c');
return resolveDomain(domain, DomainType.Client);
}
/**
@ -102,26 +142,31 @@ public class DNSUtil {
* XMPP server can be reached at for the specified domain.
* @throws Exception
*/
public static List<HostAddress> resolveXMPPServerDomain(final String domain) throws Exception {
public static List<HostAddress> resolveXMPPServerDomain(String domain) throws Exception {
domain = idnaTransformer.transform(domain);
if (dnsResolver == null) {
LOGGER.warning("No DNS Resolver active in Smack, will be unable to perform DNS SRV lookups");
List<HostAddress> addresses = new ArrayList<HostAddress>(1);
addresses.add(new HostAddress(domain, 5269));
return addresses;
}
return resolveDomain(domain, 's');
return resolveDomain(domain, DomainType.Server);
}
private static List<HostAddress> resolveDomain(String domain, char keyPrefix) throws Exception {
private static List<HostAddress> resolveDomain(String domain, DomainType domainType) throws Exception {
List<HostAddress> addresses = new ArrayList<HostAddress>();
// Step one: Do SRV lookups
String srvDomain;
if (keyPrefix == 's') {
switch (domainType) {
case Server:
srvDomain = "_xmpp-server._tcp." + domain;
} else if (keyPrefix == 'c') {
break;
case Client:
srvDomain = "_xmpp-client._tcp." + domain;
} else {
srvDomain = domain;
break;
default:
throw new AssertionError();
}
try {
List<SRVRecord> srvRecords = dnsResolver.lookupSRVRecords(srvDomain);
@ -225,4 +270,5 @@ public class DNSUtil {
}
return pos;
}
}

View File

@ -0,0 +1,23 @@
/**
*
* Copyright 2014 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smack.util;
public interface StringTransformer {
public String transform(String string);
}