1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2025-09-10 01:29:38 +02:00

Bump MiniDNS to 0.3.0-alpha1

Also add minidns-core as dependency to smack-core. This requires
increasing the minimum required Android SDK level to 9, as this is
what MiniDNS requires.
This commit is contained in:
Florian Schmaus 2018-04-24 21:41:31 +02:00
parent 6c4a02691e
commit a91ca2aebf
21 changed files with 156 additions and 237 deletions

View file

@ -10,6 +10,7 @@ dependencies {
compile 'xpp3:xpp3:1.1.4c'
compile "org.jxmpp:jxmpp-core:$jxmppVersion"
compile "org.jxmpp:jxmpp-jid:$jxmppVersion"
compile "org.minidns:minidns-core:$miniDnsVersion"
testCompile "org.jxmpp:jxmpp-jid:$jxmppVersion:tests"
testCompile "junit:junit:$junitVersion"
testCompile 'xmlunit:xmlunit:1.5'
@ -45,4 +46,4 @@ jar {
manifest {
instruction 'DynamicImport-Package', '*'
}
}
}

View file

@ -93,6 +93,7 @@ import org.jxmpp.jid.EntityFullJid;
import org.jxmpp.jid.Jid;
import org.jxmpp.jid.parts.Resourcepart;
import org.jxmpp.util.XmppStringUtils;
import org.minidns.dnsname.DNSName;
import org.xmlpull.v1.XmlPullParser;
@ -613,7 +614,8 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
}
} else {
// N.B.: Important to use config.serviceName and not AbstractXMPPConnection.serviceName
hostAddresses = DNSUtil.resolveXMPPServiceDomain(config.getXMPPServiceDomain().toString(), failedAddresses, config.getDnssecMode());
DNSName dnsName = DNSName.from(config.getXMPPServiceDomain());
hostAddresses = DNSUtil.resolveXMPPServiceDomain(dnsName, failedAddresses, config.getDnssecMode());
}
// Either the populated host addresses are not empty *or* there must be at least one failed address.
assert (!hostAddresses.isEmpty() || !failedAddresses.isEmpty());

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2003-2007 Jive Software, 2017 Florian Schmaus.
* Copyright 2003-2007 Jive Software, 2017-2018 Florian Schmaus.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -44,6 +44,7 @@ import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.jid.parts.Resourcepart;
import org.jxmpp.stringprep.XmppStringprepException;
import org.minidns.dnsname.DNSName;
/**
* Configuration to use while establishing the connection to the server.
@ -66,7 +67,7 @@ public abstract class ConnectionConfiguration {
protected final DomainBareJid xmppServiceDomain;
protected final InetAddress hostAddress;
protected final String host;
protected final DNSName host;
protected final int port;
private final String keystorePath;
@ -506,7 +507,7 @@ public abstract class ConnectionConfiguration {
private SocketFactory socketFactory;
private DomainBareJid xmppServiceDomain;
private InetAddress hostAddress;
private String host;
private DNSName host;
private int port = 5222;
private boolean allowEmptyOrNullUsername = false;
private boolean saslMechanismsSealed;
@ -624,6 +625,19 @@ public abstract class ConnectionConfiguration {
* @return a reference to this builder.
*/
public B setHost(String host) {
DNSName hostDnsName = DNSName.from(host);
return setHost(hostDnsName);
}
/**
* Set the name of the host providing the XMPP service. Note that this method does only allow DNS names and not
* IP addresses. Use {@link #setHostAddress(InetAddress)} if you want to explicitly set the Internet address of
* the host providing the XMPP service.
*
* @param host the DNS name of the host providing the XMPP service.
* @return a reference to this builder.
*/
public B setHost(DNSName host) {
this.host = host;
return getThis();
}

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2003-2005 Jive Software, 2016 Florian Schmaus.
* Copyright 2003-2005 Jive Software, 2016-2018 Florian Schmaus.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -31,6 +31,8 @@ import org.jivesoftware.smack.util.dns.HostAddress;
import org.jivesoftware.smack.util.dns.SRVRecord;
import org.jivesoftware.smack.util.dns.SmackDaneProvider;
import org.minidns.dnsname.DNSName;
/**
* Utility class to perform DNS lookups for XMPP services.
*
@ -39,27 +41,13 @@ import org.jivesoftware.smack.util.dns.SmackDaneProvider;
*/
public class DNSUtil {
public static final String XMPP_CLIENT_DNS_SRV_PREFIX = "_xmpp-client._tcp";
public static final String XMPP_SERVER_DNS_SRV_PREFIX = "_xmpp-server._tcp";
private static final Logger LOGGER = Logger.getLogger(DNSUtil.class.getName());
private static DNSResolver dnsResolver = null;
private static SmackDaneProvider daneProvider;
/**
* 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.
*
@ -96,24 +84,16 @@ public class DNSUtil {
return daneProvider;
}
/**
* Set the IDNA (Internationalizing 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 enum DomainType {
Server,
Client,
@SuppressWarnings("ImmutableEnumChecker")
enum DomainType {
server(XMPP_SERVER_DNS_SRV_PREFIX),
client(XMPP_CLIENT_DNS_SRV_PREFIX),
;
public final DNSName srvPrefix;
DomainType(String srvPrefixString) {
srvPrefix = DNSName.from(srvPrefixString);
}
}
/**
@ -131,10 +111,8 @@ public class DNSUtil {
* @return List of HostAddress, which encompasses the hostname and port that the
* XMPP server can be reached at for the specified domain.
*/
public static List<HostAddress> resolveXMPPServiceDomain(String domain, List<HostAddress> failedAddresses, DnssecMode dnssecMode) {
domain = idnaTransformer.transform(domain);
return resolveDomain(domain, DomainType.Client, failedAddresses, dnssecMode);
public static List<HostAddress> resolveXMPPServiceDomain(DNSName domain, List<HostAddress> failedAddresses, DnssecMode dnssecMode) {
return resolveDomain(domain, DomainType.client, failedAddresses, dnssecMode);
}
/**
@ -152,10 +130,8 @@ public class DNSUtil {
* @return List of HostAddress, which encompasses the hostname and port that the
* XMPP server can be reached at for the specified domain.
*/
public static List<HostAddress> resolveXMPPServerDomain(String domain, List<HostAddress> failedAddresses, DnssecMode dnssecMode) {
domain = idnaTransformer.transform(domain);
return resolveDomain(domain, DomainType.Server, failedAddresses, dnssecMode);
public static List<HostAddress> resolveXMPPServerDomain(DNSName domain, List<HostAddress> failedAddresses, DnssecMode dnssecMode) {
return resolveDomain(domain, DomainType.server, failedAddresses, dnssecMode);
}
/**
@ -165,7 +141,7 @@ public class DNSUtil {
* @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,
private static List<HostAddress> resolveDomain(DNSName domain, DomainType domainType,
List<HostAddress> failedAddresses, DnssecMode dnssecMode) {
if (dnsResolver == null) {
throw new IllegalStateException("No DNS Resolver active in Smack");
@ -174,17 +150,7 @@ public class DNSUtil {
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();
}
DNSName srvDomain = DNSName.from(domainType.srvPrefix, domain);
List<SRVRecord> srvRecords = dnsResolver.lookupSRVRecords(srvDomain, failedAddresses, dnssecMode);
if (srvRecords != null && !srvRecords.isEmpty()) {
@ -202,10 +168,10 @@ public class DNSUtil {
int defaultPort = -1;
switch (domainType) {
case Client:
case client:
defaultPort = 5222;
break;
case Server:
case server:
defaultPort = 5269;
break;
}
@ -229,7 +195,7 @@ public class DNSUtil {
private static List<HostAddress> sortSRVRecords(List<SRVRecord> records) {
// RFC 2782, Usage rules: "If there is precisely one SRV RR, and its Target is "."
// (the root domain), abort."
if (records.size() == 1 && records.get(0).getFQDN().equals("."))
if (records.size() == 1 && records.get(0).getFQDN().isRootLabel())
return Collections.emptyList();
// sorting the records improves the performance of the bisection later

View file

@ -1,61 +0,0 @@
/**
*
* Copyright 2015 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;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class IpAddressUtil {
private static final Pattern IPV4_PATTERN = Pattern.compile("^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$");
public static boolean isIPv4LiteralAddress(String string) {
Matcher matcher = IPV4_PATTERN.matcher(string);
if (!matcher.matches()) {
return false;
}
assert matcher.groupCount() == 4;
for (int i = 1; i <= 4; i++) {
String ipSegment = matcher.group(i);
int ipSegmentInt;
try {
ipSegmentInt = Integer.valueOf(ipSegment);
} catch (NumberFormatException e) {
throw new AssertionError(e);
}
if (ipSegmentInt > 255) {
return false;
}
}
return true;
}
public static boolean isIPv6LiteralAddress(final String string) {
final String[] octets = string.split(":");
if (octets.length != 8) {
return false;
}
// TODO handle compressed zeros and validate octets
return true;
}
public static boolean isIpAddress(String string) {
return isIPv4LiteralAddress(string) || isIPv6LiteralAddress(string);
}
}

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2013-2017 Florian Schmaus
* Copyright 2013-2018 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -25,6 +25,8 @@ import java.util.logging.Logger;
import org.jivesoftware.smack.ConnectionConfiguration.DnssecMode;
import org.minidns.dnsname.DNSName;
/**
* Implementations of this interface define a class that is capable of resolving DNS addresses.
*
@ -46,14 +48,14 @@ public abstract class DNSResolver {
* @param dnssecMode security mode.
* @return The list of SRV records mapped to the service name.
*/
public final List<SRVRecord> lookupSRVRecords(String name, List<HostAddress> failedAddresses, DnssecMode dnssecMode) {
public final List<SRVRecord> lookupSRVRecords(DNSName name, List<HostAddress> failedAddresses, DnssecMode dnssecMode) {
checkIfDnssecRequestedAndSupported(dnssecMode);
return lookupSRVRecords0(name, failedAddresses, dnssecMode);
}
protected abstract List<SRVRecord> lookupSRVRecords0(String name, List<HostAddress> failedAddresses, DnssecMode dnssecMode);
protected abstract List<SRVRecord> lookupSRVRecords0(DNSName name, List<HostAddress> failedAddresses, DnssecMode dnssecMode);
public final HostAddress lookupHostAddress(String name, int port, List<HostAddress> failedAddresses, DnssecMode dnssecMode) {
public final HostAddress lookupHostAddress(DNSName name, int port, List<HostAddress> failedAddresses, DnssecMode dnssecMode) {
checkIfDnssecRequestedAndSupported(dnssecMode);
List<InetAddress> inetAddresses = lookupHostAddress0(name, failedAddresses, dnssecMode);
if (inetAddresses == null || inetAddresses.isEmpty()) {
@ -76,7 +78,7 @@ public abstract class DNSResolver {
* @param dnssecMode the selected DNSSEC mode
* @return A list, either empty or non-empty, or <code>null</code>
*/
protected List<InetAddress> lookupHostAddress0(String name, List<HostAddress> failedAddresses, DnssecMode dnssecMode) {
protected List<InetAddress> lookupHostAddress0(DNSName name, List<HostAddress> failedAddresses, DnssecMode dnssecMode) {
// Default implementation of a DNS name lookup for A/AAAA records. It is assumed that this method does never
// support DNSSEC. Subclasses are free to override this method.
if (dnssecMode != DnssecMode.disabled) {
@ -85,7 +87,7 @@ public abstract class DNSResolver {
InetAddress[] inetAddressArray;
try {
inetAddressArray = InetAddress.getAllByName(name);
inetAddressArray = InetAddress.getAllByName(name.toString());
} catch (UnknownHostException e) {
failedAddresses.add(new HostAddress(name, e));
return null;

View file

@ -1,6 +1,6 @@
/**
*
* Copyright © 2013-2017 Florian Schmaus
* Copyright © 2013-2018 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -25,10 +25,11 @@ import java.util.Map;
import java.util.Map.Entry;
import org.jivesoftware.smack.SmackException.ConnectionException;
import org.jivesoftware.smack.util.StringUtils;
import org.minidns.dnsname.DNSName;
public class HostAddress {
private final String fqdn;
private final DNSName fqdn;
private final int port;
private final Map<InetAddress, Exception> exceptions = new LinkedHashMap<>();
private final List<InetAddress> inetAddresses;
@ -41,16 +42,11 @@ public class HostAddress {
* @param inetAddresses list of addresses.
* @throws IllegalArgumentException If the port is out of valid range (0 - 65535).
*/
public HostAddress(String fqdn, int port, List<InetAddress> inetAddresses) {
public HostAddress(DNSName fqdn, int port, List<InetAddress> inetAddresses) {
if (port < 0 || port > 65535)
throw new IllegalArgumentException(
"Port must be a 16-bit unsigned integer (i.e. between 0-65535. Port was: " + port);
if (StringUtils.isNotEmpty(fqdn) && fqdn.charAt(fqdn.length() - 1) == '.') {
this.fqdn = fqdn.substring(0, fqdn.length() - 1);
}
else {
this.fqdn = fqdn;
}
this.fqdn = fqdn;
this.port = port;
if (inetAddresses.isEmpty()) {
throw new IllegalArgumentException("Must provide at least one InetAddress");
@ -69,7 +65,7 @@ public class HostAddress {
* @param fqdn the domain name of the host.
* @param e the exception causing the failure.
*/
public HostAddress(String fqdn, Exception e) {
public HostAddress(DNSName fqdn, Exception e) {
this.fqdn = fqdn;
this.port = 5222;
inetAddresses = Collections.emptyList();
@ -78,7 +74,7 @@ public class HostAddress {
public String getHost() {
if (fqdn != null) {
return fqdn;
return fqdn.toString();
}
// In this case, the HostAddress(int, InetAddress) constructor must been used. We have no FQDN. And
@ -92,7 +88,7 @@ public class HostAddress {
*
* @return the fully qualified domain name or <code>null</code>
*/
public String getFQDN() {
public DNSName getFQDN() {
return fqdn;
}

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2013-2017 Florian Schmaus
* Copyright 2013-2018 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,6 +21,8 @@ import java.util.List;
import org.jivesoftware.smack.util.StringUtils;
import org.minidns.dnsname.DNSName;
/**
* A DNS SRV RR.
*
@ -44,7 +46,7 @@ public class SRVRecord extends HostAddress implements Comparable<SRVRecord> {
* @param inetAddresses list of addresses.
* @throws IllegalArgumentException fqdn is null or any other field is not in valid range (0-65535).
*/
public SRVRecord(String fqdn, int port, int priority, int weight, List<InetAddress> inetAddresses) {
public SRVRecord(DNSName fqdn, int port, int priority, int weight, List<InetAddress> inetAddresses) {
super(fqdn, port, inetAddresses);
StringUtils.requireNotNullOrEmpty(fqdn, "The FQDN must not be null");
if (weight < 0 || weight > 65535)

View file

@ -1,6 +1,6 @@
/**
*
* Copyright © 2014 Florian Schmaus
* Copyright © 2014-2018 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -28,6 +28,7 @@ import org.jivesoftware.smack.SmackException.ConnectionException;
import org.jivesoftware.smack.util.dns.HostAddress;
import org.junit.Test;
import org.minidns.dnsname.DNSName;
public class SmackExceptionTest {
@ -35,15 +36,15 @@ public class SmackExceptionTest {
public void testConnectionException() throws UnknownHostException {
List<HostAddress> failedAddresses = new LinkedList<HostAddress>();
String host = "foo.bar.example";
InetAddress inetAddress = InetAddress.getByAddress(host, new byte[] { 0, 0, 0, 0 });
DNSName host = DNSName.from("foo.bar.example");
InetAddress inetAddress = InetAddress.getByAddress(host.toString(), new byte[] { 0, 0, 0, 0 });
List<InetAddress> inetAddresses = Collections.singletonList(inetAddress);
HostAddress hostAddress = new HostAddress(host, 1234, inetAddresses);
hostAddress.setException(new Exception("Failed for some reason"));
failedAddresses.add(hostAddress);
host = "barz.example";
inetAddress = InetAddress.getByAddress(host, new byte[] { 0, 0, 0, 0 });
host = DNSName.from("barz.example");
inetAddress = InetAddress.getByAddress(host.toString(), new byte[] { 0, 0, 0, 0 });
inetAddresses = Collections.singletonList(inetAddress);
hostAddress = new HostAddress(host, 5678, inetAddresses);
hostAddress.setException(new Exception("Failed for some other reason"));

View file

@ -0,0 +1,36 @@
/**
*
* Copyright 2018 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;
import static org.junit.Assert.assertEquals;
import org.jivesoftware.smack.util.DNSUtil.DomainType;
import org.junit.Test;
public class DnsUtilTest {
@Test
public void simpleDomainTypeTest() {
DomainType client = DomainType.client;
assertEquals(DNSUtil.XMPP_CLIENT_DNS_SRV_PREFIX, client.srvPrefix.ace);
DomainType server = DomainType.server;
assertEquals(DNSUtil.XMPP_SERVER_DNS_SRV_PREFIX, server.srvPrefix.ace);
}
}

View file

@ -1,46 +0,0 @@
/**
*
* Copyright 2017 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;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class IpAddressUtilTest {
@Test
public void isIpV4AddressTest() {
String ipv4 = "122.20.221.11";
boolean isIpV4 = IpAddressUtil.isIPv4LiteralAddress(ipv4);
assertTrue(isIpV4);
}
@Test
public void isInvalidIpV4AddressTest() {
String ipv4 = "122.20.221.11.1";
boolean isIpV4 = IpAddressUtil.isIPv4LiteralAddress(ipv4);
assertFalse(isIpV4);
}
@Test
public void isInvalidIpV4AddressTest2() {
String ipv4 = "122.20.256.11";
boolean isIpV4 = IpAddressUtil.isIPv4LiteralAddress(ipv4);
assertFalse(isIpV4);
}
}