zeroconf icon indicating copy to clipboard operation
zeroconf copied to clipboard

What to do when only a TXT property changes in an mDNS record?

Open stodge opened this issue 1 month ago • 6 comments

What does the mDNS spec say about publishing a mDNS record when only a TXT property has changed? Looking at the zeroconf code, I have to cancel the existing mDNS record before publishing a new one. I'm trying to find where this is defined in the spec - should I be able to re-publish the same service but with the modified TXT properties without cancelling the existing record? Thanks

stodge avatar Oct 30 '25 20:10 stodge

After a bit of digging I think https://datatracker.ietf.org/doc/html/rfc6762#section-10.2 is the answer. That states when a record is invalidated, the "cache-flush" bit of the "rrclass" property should be set; that's the 16-bit "class" field. You'll see in the Record.java this as a constant value, 0x8001, so that bit it always set (the other set bit indicates the record is an "internet" class, see RFC 1035 for that)

So if you want to invalidate something you send a new record with that bit set, and the recipient must replace any existing record with the new one. I can't see any requirement to send a TTL=0 record before you cancel the old service - this is just a result of the API design.

I've taken a punt at a fix for this on the "reannounce" branch if you want to try it - there are two new methods in the Service class:

  • boolean isMine() - returns true if this was created from the Builder, false if it was heard on the network
  • boolean setText(Map<String,String> text) - for Services you've created (where isMine()==true), this method will update the text record, and if the service has been announced already will reannounce it.

Give it a test and let me know.

faceless2 avatar Oct 31 '25 09:10 faceless2

Awesome, thanks. Not sure when exactly I'll get to try it out, but it's to add a feature to our emulator that is sorely needed.

stodge avatar Oct 31 '25 13:10 stodge

I just had to give it a go this morning!

Added code to my emulator:

if (!this.service.isMine()) {
    return;
}

final Map<String, String> txt = this.buildTextProperties();
this.service.setText(txt);

But I always get this error:

Oct 31, 2025 6:31:24 A.M. com.bfo.zeroconf.Zeroconf log
SEVERE: ListenerThread exception
java.lang.IllegalStateException: Can't replace text on a record you didn't create
	at com.bfo.zeroconf.Service.setText(Service.java:127)
	at com.bfo.zeroconf.Zeroconf.processAnswer(Zeroconf.java:1127)
	at com.bfo.zeroconf.Zeroconf.processAnswer(Zeroconf.java:1121)
	at com.bfo.zeroconf.Zeroconf.processPacket(Zeroconf.java:833)
	at com.bfo.zeroconf.Zeroconf$ListenerThread.run(Zeroconf.java:723)

stodge avatar Oct 31 '25 13:10 stodge

Whoops. Pushed a fix, see if that helps.

faceless2 avatar Nov 02 '25 18:11 faceless2

Will do, thanks!

stodge avatar Nov 03 '25 15:11 stodge

My first quick test is successful. I'll try more in depth testing later. Thanks.

stodge avatar Nov 03 '25 16:11 stodge

I've only been able to do minimal testing, but so far it looks good. I don't think I'll be able to do more in-depth testing for a while.

stodge avatar Nov 05 '25 16:11 stodge

I did some more testing and it works for me. So two thumbs up!

stodge avatar Nov 19 '25 15:11 stodge