IllegalArgumentException in SRVRecord constructor

When trying form an XMPP connection, Smack 4.2.0 can emit the following unchecked exception:

Stacktrace:

java.lang.IllegalArgumentException: Must provide at least one InetAddress
at org.jivesoftware.smack.util.dns.HostAddress.(HostAddress.java:55)
at org.jivesoftware.smack.util.dns.SRVRecord.(SRVRecord.java:47)
at org.jivesoftware.smack.util.dns.minidns.MiniDnsResolver.lookupSRVRecords0(MiniDnsResolver.java:97)
at org.jivesoftware.smack.util.dns.DNSResolver.lookupSRVRecords(DNSResolver.java:48)
at org.jivesoftware.smack.util.DNSUtil.resolveDomain(DNSUtil.java:187)
at org.jivesoftware.smack.util.DNSUtil.resolveXMPPServiceDomain(DNSUtil.java:136)
at org.jivesoftware.smack.AbstractXMPPConnection.populateHostAddresses(AbstractXMPPConnection.java:626)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.connectUsingConfiguration(XMPPTCPConnection.java:556)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.connectInternal(XMPPTCPConnection.java:888)
at org.jivesoftware.smack.AbstractXMPPConnection.connect(AbstractXMPPConnection.java:377)

Device: Samsung SM-A320FL running Android 6.0.1
Smack version: 4.2.0 (4.2.0-rc2-49-gb9b8b1a-4.2 2017-03-10)
Network connectivity: WiFi

I have stepped through this in the debugger, and it looks like the problem is in MiniDnsResolver.lookupSRVRecords0

lookupHostAddress0 returns an empty list, which is passed to SRVRecord’s constructor and therefore to HostAddress’s, causing the IllegalArgumentException

The reason that lookupHostAddress0 returns an empty list is that the SRV record resolved to an A record. When lookupHostAddress0 tries to resolve that, both the A and AAAA queries return the following results (C&P from Android Studio debugger below):

aResult = {ResolverResult@7063}
data = {Collections$UnmodifiableSet@7065} size = 0
dnssecResultNotAuthenticException = null
isAuthenticData = false
question = {Question@7066} "{redacted domain}.\tIN\tA"
resolutionUnsuccessfulException = null
responseCode = {DNSMessage$RESPONSE_CODE@7067} "NO_ERROR"
unverifiedReasons = null
shadow$klass = {Class@1910} "class de.measite.minidns.hla.ResolverResult"
shadow$monitor = -2106162067

aaaaResult = {ResolverResult@7064}
data = {Collections$UnmodifiableSet@7071} size = 0
dnssecResultNotAuthenticException = null
isAuthenticData = false
question = {Question@7072} "{redacted domain}.\tIN\tAAAA"
resolutionUnsuccessfulException = null
responseCode = {DNSMessage$RESPONSE_CODE@7067} "NO_ERROR"
unverifiedReasons = null
shadow$klass = {Class@1910} "class de.measite.minidns.hla.ResolverResult"
shadow$monitor = -2111977310

Note that DNSSEC is disabled so the shouldAbortIfNotAuthentic checks return false

The output of ‘dig’ for the A-record is shown below:

C:\lib\BIND>dig {redacted domain}

; <<>> DiG 9.10.6 <<>> {redacted domain}
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 9760
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4000
;; QUESTION SECTION:
;{redacted domain}. IN A

;; Query time: 11 msec
;; SERVER: 192.168.8.1#53(192.168.8.1)
;; WHEN: Thu Oct 12 17:03:54 GMT Daylight Time 2017
;; MSG SIZE rcvd: 62

The fact these records don’t resolve properly is a problem with our DNS setup. However, even so, Smack should not emit the unchecked exception in this scenario.

Would you be able to confirm if we’re doing anything wrong, or if not fix this exception? Thanks very much.

You are right. Smack’s MiniDnsResolver does not correctly handle the case when NOERROR is returned together with an empty answer section. Created SMACK-781.