From 3129165a1c39f51cab5606f17b446ae88996ea99 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Wed, 28 Dec 2016 23:18:28 +0100 Subject: [PATCH] Add ConnectionConfiguration.setHostAddress(InetAddress) In previous Smack versions, it was possible to set the host's IP address via setHost(String), this is no longer possible (since the support for DNSSEC was introduced). The new setHostAddress(InetAddress) allows it again to explicitly specifiy the XMPP service's host IP. --- .../smack/AbstractXMPPConnection.java | 11 +++++-- .../smack/ConnectionConfiguration.java | 29 +++++++++++++++++++ .../org/jivesoftware/smack/util/DNSUtil.java | 11 ++++++- .../smack/util/dns/DNSResolver.java | 4 +-- .../smack/util/dns/HostAddress.java | 15 +++------- 5 files changed, 53 insertions(+), 17 deletions(-) diff --git a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java index 6f6237d12..c934037b4 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java @@ -602,12 +602,17 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { */ protected List populateHostAddresses() { List failedAddresses = new LinkedList<>(); - // N.B.: Important to use config.serviceName and not AbstractXMPPConnection.serviceName - if (config.host != null) { + if (config.hostAddress != null) { + hostAddresses = new ArrayList<>(1); + HostAddress hostAddress = new HostAddress(config.port, config.hostAddress); + hostAddresses.add(hostAddress); + } + else if (config.host != null) { hostAddresses = new ArrayList(1); - HostAddress hostAddress = DNSUtil.getDNSResolver().lookupHostAddress(config.host, failedAddresses, config.getDnssecMode()); + HostAddress hostAddress = DNSUtil.getDNSResolver().lookupHostAddress(config.host, config.port, failedAddresses, config.getDnssecMode()); hostAddresses.add(hostAddress); } else { + // N.B.: Important to use config.serviceName and not AbstractXMPPConnection.serviceName hostAddresses = DNSUtil.resolveXMPPServiceDomain(config.getXMPPServiceDomain().toString(), failedAddresses, config.getDnssecMode()); } // If we reach this, then hostAddresses *must not* be empty, i.e. there is at least one host added, either the diff --git a/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java b/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java index b41ab46b0..79ef71e67 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java @@ -17,6 +17,7 @@ package org.jivesoftware.smack; +import java.net.InetAddress; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -62,6 +63,7 @@ public abstract class ConnectionConfiguration { */ protected final DomainBareJid xmppServiceDomain; + protected final InetAddress hostAddress; protected final String host; protected final int port; @@ -134,6 +136,7 @@ public abstract class ConnectionConfiguration { if (xmppServiceDomain == null) { throw new IllegalArgumentException("Must define the XMPP domain"); } + hostAddress = builder.hostAddress; host = builder.host; port = builder.port; @@ -509,6 +512,7 @@ public abstract class ConnectionConfiguration { private boolean debuggerEnabled = SmackConfiguration.DEBUG; private SocketFactory socketFactory; private DomainBareJid xmppServiceDomain; + private InetAddress hostAddress; private String host; private int port = 5222; private boolean allowEmptyOrNullUsername = false; @@ -599,12 +603,37 @@ public abstract class ConnectionConfiguration { return setResource(Resourcepart.from(resource.toString())); } + /** + * Set the Internet address of the host providing the XMPP service. If set, then this will overwrite anything + * set via {@link #setHost(String)}. + * + * @param address the Internet address of the host providing the XMPP service. + * @return a reference to this builder. + * @since 4.2 + */ + public B setHostAddress(InetAddress address) { + this.hostAddress = address; + return getThis(); + } + + /** + * 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(String host) { this.host = host; return getThis(); } public B setPort(int port) { + if (port < 0 || port > 65535) { + throw new IllegalArgumentException( + "Port must be a 16-bit unsiged integer (i.e. between 0-65535. Port was: " + port); + } this.port = port; return getThis(); } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/DNSUtil.java b/smack-core/src/main/java/org/jivesoftware/smack/util/DNSUtil.java index 391e03034..17ed2a46b 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/DNSUtil.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/DNSUtil.java @@ -196,8 +196,17 @@ public class DNSUtil { addresses.addAll(sortedRecords); } + int defaultPort = -1; + switch (domainType) { + case Client: + defaultPort = 5222; + break; + case Server: + defaultPort = 5269; + break; + } // Step two: Add the hostname to the end of the list - HostAddress hostAddress = dnsResolver.lookupHostAddress(domain, failedAddresses, dnssecMode); + HostAddress hostAddress = dnsResolver.lookupHostAddress(domain, defaultPort, failedAddresses, dnssecMode); if (hostAddress != null) { addresses.add(hostAddress); } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/dns/DNSResolver.java b/smack-core/src/main/java/org/jivesoftware/smack/util/dns/DNSResolver.java index 052795bda..dde188959 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/dns/DNSResolver.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/dns/DNSResolver.java @@ -47,13 +47,13 @@ public abstract class DNSResolver { protected abstract List lookupSRVRecords0(String name, List failedAddresses, DnssecMode dnssecMode); - public final HostAddress lookupHostAddress(String name, List failedAddresses, DnssecMode dnssecMode) { + public final HostAddress lookupHostAddress(String name, int port, List failedAddresses, DnssecMode dnssecMode) { checkIfDnssecRequestedAndSupported(dnssecMode); List inetAddresses = lookupHostAddress0(name, failedAddresses, dnssecMode); if (inetAddresses == null) { return null; } - return new HostAddress(name, inetAddresses); + return new HostAddress(name, port, inetAddresses); } protected List lookupHostAddress0(String name, List failedAddresses, DnssecMode dnssecMode) { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/dns/HostAddress.java b/smack-core/src/main/java/org/jivesoftware/smack/util/dns/HostAddress.java index e9ae53717..e0eb98aed 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/dns/HostAddress.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/dns/HostAddress.java @@ -33,17 +33,6 @@ public class HostAddress { private final Map exceptions = new LinkedHashMap<>(); private final List inetAddresses; - /** - * Creates a new HostAddress with the given FQDN. The port will be set to the default XMPP client port: 5222 - * - * @param fqdn Fully qualified domain name. - * @throws IllegalArgumentException If the fqdn is null. - */ - public HostAddress(String fqdn, List inetAddresses) { - // Set port to the default port for XMPP client communication - this(fqdn, 5222, inetAddresses); - } - /** * Creates a new HostAddress with the given FQDN. The port will be set to the default XMPP client port: 5222 * @@ -69,6 +58,10 @@ public class HostAddress { this.inetAddresses = inetAddresses; } + public HostAddress(int port, InetAddress hostAddress) { + this("", port, Collections.singletonList(hostAddress)); + } + /** * Constructs a new failed HostAddress. This constructor is usually used when the DNS resolution of the domain name * failed for some reason.