Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

A simple CLI DNS-SD browser...

I am learning how to use DNS-SD from swift and have created a basic CLI app, however I am not getting callback results.

I can get results from cli. Something I am doing wrong here?

dns-sd -G v6 adet.local
10:06:08.423  Add  40000002      22  adet.local.                            FE80:0000...

dns-sd -B _adt._udp.
11:19:10.696  Add        2  22 local.               _adt._udp.           adet
import Foundation
import dnssd

var reference: DNSServiceRef?

func dnsServiceGetAddrInfoReply(ref: DNSServiceRef?, flags: DNSServiceFlags, interfaceIndex: UInt32, errorCode: DNSServiceErrorType, hostname: UnsafePointer<CChar>?, address: UnsafePointer<sockaddr>?, ttl: UInt32, context: UnsafeMutableRawPointer?) {
    print("GetAddr'd")
    print(hostname.debugDescription.utf8CString)
    print(address.debugDescription.utf8CString)
}

var error = DNSServiceGetAddrInfo(&reference, 0, 0, DNSServiceProtocol(kDNSServiceProtocol_IPv6), "adet.local", dnsServiceGetAddrInfoReply, nil)
print("GetAddr: \(error)")

func dnsServiceBrowseReply(ref: DNSServiceRef?, flags: DNSServiceFlags, interfaceIndex: UInt32, errorCode: DNSServiceErrorType, serviceName: UnsafePointer<CChar>?, regType: UnsafePointer<CChar>?, replyDomain: UnsafePointer<CChar>?, context: UnsafeMutableRawPointer?) {
    print("Browsed")
    print(serviceName.debugDescription.utf8CString)
    print(replyDomain.debugDescription.utf8CString)
}

error = DNSServiceBrowse(&reference, 0, 0, "_adt._udp", nil, dnsServiceBrowseReply, nil)
print("Browse: \(error)")

Foundation.RunLoop.main.run()

Info.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>NSLocalNetworkUsageDescription</key>
	<string>By the Hammer of Grabthor</string>
	<key>NSBonjourServices</key>
	<array>
		<string>_adt._udp.</string>
		<string>_http._tcp.</string>
		<string>_http._tcp</string>
		<string>_adt._udp</string>
	</array>
</dict>
</plist>
Answered by DTS Engineer in 842754022
Ironically, I tried to find a good example of the simple case

I have an example in this post.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Ah, and when I run the test app, I don't see any callbacks:

GetAddr: 0
Browse: 0

Ran across a complete sample on Github. Results aren't processed until you call:

error = DNSServiceProcessResult(reference)
print("ProcessResult \(error)")

I am learning how to use DNS-SD from swift and have created a basic CLI app, however I am not getting callback results.

I can get results from cli. Something I am doing wrong here?

Sort of. The DNS-SD APIs is a particularly low level API which was architected to be able to work with as little of the system "standard" architecture as possible. Most of our APIs either:

  1. Implicitly "attach" what the runloop of the current thread and automatically use that thread for callbacks.

  2. Require the caller to specific a callback target (typically either a dispatch queue or runloop). DNS-SD actually follows this model with "DNSServiceSetDispatchQueue".

You've actually failed to do #2, which is where your initial problem starts.

That leads to here:

Ran across a complete sample on Github. Results aren't processed until you call: error = DNSServiceProcessResult(reference)

DNS-SD is actually unusual in that it implements a 3rd option, namely DNSServiceProcessResult. What DNSServiceProcessResult actually does is manually read and process the bonjour data, then call your apps callbacks as it processes that data. Our documentation doesn't do a very good job of explaining this, but it's actual "role" here is as an alternative to "DNSServiceSetDispatchQueue".

However, here is one "hint" of what's actually going on here:

"After using DNSServiceSetDispatchQueue on a DNSServiceRef, calling DNSServiceProcessResult on the same DNSServiceRef will result in undefined behavior and should be avoided."

The behavior here is undefined because you'll end up having two different API paths trying to pull data from the same data source and then deliver that data to the same set of callbacks. What will actually happen in that case, is very difficult to predict as it depends entirely on exactly what threads are involved and what context DNSServiceProcessResult is called from. The only guarantee is that it's likely to be weird.

I'll also say that this description is a quite odd and slightly misses the point of DNSServiceProcessResult, at least on our platforms:

"Use DNSServiceRefSockFD in conjunction with a run loop or select() to determine the presence of a response from the server before calling this function to process the reply without blocking."

This is a case of explaining the complicated/advanced case while ignoring the obvious one. There are cases where you MIGHT use this kind of approach, but the majority of apps (on our platform) would either build around dispatch or target the main runloop, avoiding DNSServiceProcessResult entirely. The basic/common case is actually the sentence that follow:

"Call this function at any point if it is acceptable to block until the daemon’s response arrives."

...that is, for example, something like a basic command line tool that was only interested in bonjour traffic could simply loop on DNSServiceProcessResult until it got whatever it was interested in and decided to stop.

Ironically, I tried to find a good example of the simple case here but didn't find a perfect example as the mDNSResponder examples are actually designed to be more "complete" and actually demonstrate how this would work in a fully functional Windows/Posix app/process. However, you can see how this would work in dns-sd.c, even if it's more complicated than you'd need.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Ironically, I tried to find a good example of the simple case

I have an example in this post.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

A simple CLI DNS-SD browser...
 
 
Q