Overhaul mDNS to allow arbitrary records (supports DNS Service Discovery)#1326
Overhaul mDNS to allow arbitrary records (supports DNS Service Discovery)#1326george-palmsens wants to merge 12 commits into
Conversation
abd89c5 to
0345238
Compare
17f3a0d to
cc0fd7a
Compare
1a2a462 to
decb55b
Compare
|
Apologies for spamming the CI. I have added a back compatibility shim for the old style DNS hooks. Defining |
af4bbfa to
64e6fbf
Compare
7a3d07a to
6de96b6
Compare
|
Added support for "Additional RRs" in the generated response, with a corresponding hook. This is a |
56ec79c to
7e9afdf
Compare
|
Hi @george-palmsens , you're doing a great job. Please allow me time to review and test the changes, most importantly: keeping thing downward compatible. |
|
@george-palmsens Thank you for the implementation, just tested it and found it to work great! For documentation: Some example code with the hooks & usage of Regarding the TXT records: Currently only one printable key/value pair per TXT record is supported. The current approach works fine for me, but the specification generally expects one TXT records for most cases (6.8.) and putting multiple key/value pairs inside the one (and recommends adding I've thought about this for a bit, but I don't know how a nice API for this would look. Perhaps something like this for the "full" approach? Alternatively when ignoring binary data, I see two other options:
|
|
@david-sawatzke Thanks for test-driving the code, great to hear it works! Where should documentation be added? Just in the relevant headers, or is there an example/website docs location I should be putting it? You're definitely right about TXT records. I'll need to get my head back into the code and look at your suggestions and I'll get back to you 👍 |
|
@david-sawatzke So the key/value pair thing is DNS-SD specific - this PR doesn't specifically care about DNS-SD, so I'd feel uncomfortable adding them into the actual structure of the code. So I would aim for making the text record simply contain an arbitrary number of string entries. And if you want to use those for As such I think I would just alter the struct to take a pointer to an array of strings, rather than a single entry. So it would look like: typedef struct xDNSRecord
{
uint16_t usRecordType;
/* How to serve this record.
* See `dnsRECORD_SERVE_NO`, `dnsRECORD_SERVE_ADDITIONAL` and `dnsRECORD_SERVE_ANSWER`. */
BaseType_t uxServeRecord;
const char * pcName;
union
{
char * pcPtrRecord;
struct
{
const char * pcTarget;
uint16_t usPort;
} xSrvRecord;
struct
{
const char * const * pcStrings;
UBaseType_t uxNumStrings;
} xTxtRecord;
} xData;
} DNSRecord_t;This would still stop us from serving strings with null bytes, but it sounds like we can tolerate that...? |
13b5e0b to
6b7700f
Compare
I don't know, but I'd guess it should be in the headers anyways so there first?
At a quick look I haven't found a mDNS-SD service type that requires it, so I think it's fine.
This approach sounds good to me, a bit more annoying in the mDNS-SD usecase (as the string needs to be mutated to change the value if the value is already stored as a string), but also supports encodings outside RFC1464 |
I haven't established how any of this works if you want to change the records being served dynamically. I don't think the current API supports it - because at any given moment the IP task could be iterating over the records. You would need to do some sort of deep copy in the hook, which seems very impractical. EDIT: We could add an additional hook for when the DNS code is finished using the records. That would give an acquire/release pair that the user could work with to update the DNS records from another thread. That would compose nicely with what we have now. |
58de0e1 to
5ec0cc0
Compare
Ah, you're right, I've misunderstood. I thought As a hacky approach, one could also update the contents of the records in Then I've probably also misunderstood I think the best option could be to call EDIT: as |
Yeah it is called every request - but then the IP task iterates through the returned records. And yeah if you do in-place mutation in the callback then you will be fine 👍 . That is a workable solution. |
| #else | ||
| NetworkEndPoint_t xEndPoint; | ||
|
|
||
| if( xSet->pxDNSRecords == NULL ) |
There was a problem hiding this comment.
Will xSet->pxDNSRecords in DNS_GetRecords ever not be NULL? Even if yes, should it just be overwritten anyways?
There was a problem hiding this comment.
It is not NULL in the case where there are multiple questions. GetRecords is called in the question loop.
a81c454 to
cf405a0
Compare
This adds support for DNS-SD
cf405a0 to
57c267e
Compare
8288d2d to
0155f03
Compare
|
@david-sawatzke Multiple strings are now present, and I've also generally tidied and improved the implementation, and added example code. Note to reviewers, coverage is <100% in the DNS code but this is also true on main. It is not caused by this PR. |
|
Tested it, also works great for me. Thank you @george-palmsens for the changes & cleanup, and the example in the header! |
This changes the DNS hook to return a list of records to serve over mDNS. By setting an appropriate set of records, this satisfies DNS-SD (Avahi, Bonjour, etc).
An "appropriate set of records" looks like:
Other things that have been changed to accomodate this:
Checklist:
I have tested my changes locally, and verified the device is discoverable through Avahi. I have not run an application level test suite.
I have added a shim that allows the old hooks to still work via a back-compatibility flag, I hope that is a fine approach.
I have added the necessary unit tests that reach 100% coverage. A few isolated cases had to be ignored from the coverage report since they are defensive checks that are already caught earlier in the logic.
Requests for assistance:
Related Issue
See #1284
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.