(m)DNS name resolution in Foundation?

Is there a way to resolve an mDNS name (e.g. "foo.local") to its IP address in Foundation? I believe URLRequest does this implicitly, but in my case I need to pass an IP address (as a string!) to an underlying C library (libmodbus). I tried passing it the mDNS name directly and it balked.

There are libraries out there to do this, but this feels like something that should be part of Foundation.

One possible solution is wrapping CFHost, although that’s pretty clunky and not immediately async-friendly.

Just feels like something that should be part of Swift (or Foundation).

It’s not built in to Foundation, but looks like Apple provides a first-party package for this: GitHub - apple/swift-async-dns-resolver: A Swift library for asynchronous DNS requests, wrapping c-ares with Swift-friendly APIs and data structures.

Couldn’t find docs anywhere other than a third-party site though: https://swiftinit.org/docs/swift-async-dns-resolver/asyncdnsresolver

2 Likes

Note that on Apple's platforms this will prefer to use the tool built into Apple's SDK, dnssd: this is one first-party solution for mDNS name resolution on Apple's platforms. Documentation is here.

Note however that if you're actually interacting with Bonjour you may find it better to use a higher-level API, such as NWBrowser. This is a bit more Bonjour-aware, and works a bit more elegantly.

I believe URLRequest does this implicitly, but in my case I need to
pass an IP address (as a string!) to an underlying C library
(libmodbus).

This speaks to why there’s no high-level API for this primitive. The BSD Sockets resolve-then-connect approach worked well when BSD Sockets was originally designed, but it requires a lot of additional code when deployed to the modern world. Apple networking APIs use a connect-by-name design so that you don’t have to write that additional code.

I discuss a bunch of the background to this in TN3151 Choosing the right networking API, specifically in the Connect by name and BSD Sockets best practices section.

As to what you should actually do here, it kinda depends on what your underlying C library does with the IP address you pass it. I suspect that you plan to deploy this code in an environment where it’ll work without Happy Eyeballs. In that case you have a couple of options:

  • Use one of the Swift Asynchronous DNS Resolver package. This makes the most sense if you want to support Apple and non-Apple platforms.

  • Call DNS-SD directly. This DevForums post shows how to do that (although it uses DNSServiceResolve, and you’ll want to change that to DNSServiceGetAddrInfo).

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple

3 Likes

I definitely need it to work on both macOS and Linux. Given that the URL system can do this implicitly, I had hoped to prompt a discussion about surfacing that functionality to all.

Of course I can use one of the several third-party packages I’ve found, but it rubs me the wrong way to duplicate functionality that already exists.

1 Like