How to use DNSServiceReconfirmRecord?

TL;DR: How does one use DNSServiceReconfirmRecord() to invalidate mDNS state of a device that's gone offline?

I'm using the DNSServiceDiscovery API (dns_sd.h) for a local P2P service. The problem I'm trying to solve is how to deal with a peer that abruptly loses connectivity, i.e. by turning off WiFi or simply by moving out of range or otherwise losing connectivity. In this situation there is of course no notification that the peer device has gone offline; it simply stops sending any packets.

After my own timeout mechanism determines the peer is not responding, I mark it as offline in my own data structures. The problem is how to discover when/if it comes back online later. My DNSServiceBrowse callback won't be invoked because mDNS doesn't know the device went offline in the first place.

I am trying to use DNSServiceReconfirmRecord, which appears to be for exactly this use case -- "Instruct the daemon to verify the validity of a resource record that appears to be out of date (e.g. because TCP connection to a service's target failed.)" However my attempts always return a BadReference error (-65541). The function requires me to pass a DNS record, and the only one I know is the TXT record; perhaps it needs a different one? Which, and how would I get it?

Thanks!

Answered by DTS Engineer in 874061022

Hey Jens, it’s been a while.

which appears to be for exactly this use case

Yep.

my attempts always return a BadReference error (-65541).

Yeah, this is not an easy API to use correctly. There are two parts to it:

  1. Actually calling the DNSServiceReconfirmRecord API.
  2. Deciding what record data to pass in.

That kDNSServiceErr_BadReference error suggests you’re having problems with the first step, not the second. Regardless, I have suggestions for both of these in this post.

Share and Enjoy

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

Accepted Answer

Hey Jens, it’s been a while.

which appears to be for exactly this use case

Yep.

my attempts always return a BadReference error (-65541).

Yeah, this is not an easy API to use correctly. There are two parts to it:

  1. Actually calling the DNSServiceReconfirmRecord API.
  2. Deciding what record data to pass in.

That kDNSServiceErr_BadReference error suggests you’re having problems with the first step, not the second. Regardless, I have suggestions for both of these in this post.

Share and Enjoy

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

Thanks Quinn, that worked like a charm!

I suspect that this call will also inform all the other peers on the network that the service is offline, since they'll see the mDNS query and the lack of reply. True?

Glad to hear you get it working.

this call will also inform all the other peers on the network that the service is offline

Right. Sections 10.4 and 10.5 of RFC 6762 Multicast DNS describe the mechanics of this.

Share and Enjoy

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

I may have spoken too soon -- it worked for me on macOS [15.7.3] but a co-worker reports it's still returning BadReference on iOS [26?]. From my logging I can see that the arguments passed in this specific failing call are as follows:

vector<uint8_t> record = encodeDNS("multipeer-todo-0F2BDA36._couchbaseP2P._tcp,com\\.couchbase\\.multipeer\\.todo.local.");
err = DNSServiceReconfirmRecord(
    0,  // flags
    15,  // interface; this is what was reported by service discovery
    "_couchbaseP2P._tcp,com\.couchbase\\.multipeer\\.todo.local.",  // fullname
    kDNSServiceType_PTR,
    kDNSServiceClass_IN,
    record.size(), record.data() );

where encodeDNS is a function I wrote to generate an encoded DNS record, which has unit tests to verify it correctly handles escape sequences.

Note we're using a service subtype. I was worried this might require special handling, but at least on macOS it didn't. Perhaps that's different on iOS?

The kDNSServiceErr_BadReference error is odd in that the function doesn't take a service reference.

(oops: in the fullname string above I forgot to escape the backslash before .couchbase. The actual call did have the backslash.)

I’m confused by the full name value you’re using. In the post I referenced earlier I showed that the full name for a SSH PTR record would be something like _ssh._tcp.local., so I don’t understand where you’re getting _couchbaseP2P._tcp,com\.couchbase\.multipeer\.todo.local. from. Are you actually trying to reconfirm the PTR? Or some other record type?

Share and Enjoy

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

We're using a service subtype, which is the stuff after the comma. (Our library defines the service type, but each app that uses it provides a different subtype so they don't see services published by other apps.)

My co-worker found out (from Google's AI...) that in this case the fullName should be of the form <Subtype>._sub.<ServiceType>.<Transport>.<Domain> and the record should be the encoded form of <InstanceName>.<ServiceType>.<Transport>.<Domain>. I changed my code accordingly and now it works on all platforms.

How to use DNSServiceReconfirmRecord?
 
 
Q