From Part 1 and Part 2, you can see we have grabbed the a request and parsed it successfully. The next step is to actually answer the request. At this point, I started using Wireshark. I didn’t use it in the beginning because I totally forgot about it 🙂
I found this interesting post – https://justanapplication.wordpress.com/category/dns/dns-resource-records/dns-txt-record/ – which seemed to describe the response format I was interested in.
It’s at this point that I realise endianness might be an issue! If you don’t know what endianness is, I envy you. Oh joy of joys. So after reversing all the arrays, my packet looked like a closer match and, success! A response!
Whilst this response doesn’t actually contain any information, it showed me that something was actually working. I then restored the code to include the one TXT answer. The packet appeared in Wireshark, but was malformed.
After more reading, I realised it was the way I was generating the name. I had just passed it in as a UTF8 Byte, but rather it should be broken out by the periods with length fields too. This explains a lot of the questions marks! More tinkering and BINGO! An empty TXT record response!
I was now feeling very confident and decided to see if my little Console App could actually respond to a genuine request. I downloaded a Chrome Store app called mDNS Browser (https://chrome.google.com/webstore/detail/mdns-browser/kipighjpklofchgbdgclfaoccdlghidp?utm_source=chrome-app-launcher-info-dialog). I had stopped using Bonjour Browser as I felt I kept needing to restart it. Running them both side by side….and nothing! I could see the mDNS request (after discovering you could filter Wireshark with mDNS!)
This was disappointing as I could see my console was sending a response, which I was knew was well formed. I played around a little, but still no joy. I did then notice that my app was answering its own queries!!
I made a small modification so that it only processed queries and not responses. This thankfully cut down the output. I’m not sure why I didn’t spot this before, but I assumed it was all the devices on my network advertising themselves. Running the request again:
Single request, single response. But nothing in Wireshark.
The app wasn’t generating any errors and I would receive and respond to multiple requests, so I was confident that the sockets themselves weren’t the problem.
One of things I had noticed when trying to get the receive to work, was that I had to enable the MulticastLoopback setting on the Socket. It then struck me that the reason I might not be seeing any response traffic in Wireshark was because the broadcast was going out on the loopback (this is 127.0.0.1 and prevents the network traffic going down too low in the networking stack) address!
Armed with this idea, I found an interesting post on StackOverflow (https://stackoverflow.com/questions/22504272/troubleshooting-udp-multicast-issue). I copied the snipped of code, tweaked it a little and reran my test. Amazingly, it worked!
Wireshark showed one _services.dns-sd request and one response with a TXT record. I checked the content and it matched up to my response!
Unfortunately, the mDNS Browser didn’t show anything.
There are two reasons I can think of; Either it’s not receiving the response or the response isn’t valid enough for it.
At this stage, It’s worth going back to brass tacks. I’ve got a good understanding of the DNS records and how they are structured, so I fired up my Homekit console app (which uses Apple’s Bonjour to generate the records) so get an example of what I need to be returning.
Wireshark yielded this:
So I have the broad stokes in place. I’m going to now try and just emulate this, using a simple A record to get me rolling.
Not a bad first attempt. The \004 and \005 artefacts were odd invisible characters from a copy paste, so I cleaned them up.
Next, I need to add an A type record. I thought this was straight foward, but in the process of comparing it to the sample Bonjour record, I noticed something odd.
The word local wasn’t actually spelled out. This implied it was a keyword or something. On inspection of the other records, in the Answers section, I found it to be the same. Reviewing the records in more details revealed there is some sort of pointer mechanism at work. I’m not 100% sure about this yet, but the PTR record seems to point to the TXT record
This, I’m guessing, is some soft of space saving approach. I’m just not 100% sure if it’s actually necessary. For the sake of keeping my code simple, I’m going to assume it’s optional 🙂
After much messing around, I still wasn’t seeing my responses in the Browser, so I decided to trim the packet down to the pointer. I also noticed that all of the other responses, included the original query, so I included that too.
Still no joy. I then discovered I was doing something stupid. Using the MDNS browser, I could see some responses from the devices on my network, but my own response never showed up. It was then I noticed the destination!
The other responses were directed at the source IP, where my own response was simply targeted at the multicast address!! In hindsight, it makes sense to respond directly to the person asking. I quick tweak of my code and bingo!
Encouraged by this, I restored all the other parts of the code to return the A records and PTR, SVR and TXT records too. Unfortunately, these didn’t appear in either MDNS browser nor the Bonjour Browser. For some reason, I decided to see if my iPhone Browser would work! Amazingly….
So my HAP entry appear. I drilled down….
And there is was! My TXT record and my IP addresses. I don’t know how it got the IP6 addresses, but I didn’t card. Feeling very optimistic, I updated the TXT record with the required Homekit TXT record fields and opened the Homekit app on my phone. Amazingly, my bridge appeared!!!!
Excellent. Next step is to deploy this little app onto my Raspberry Pi and see if it still works! I should point out that my implementation is woefully incomplete as regards the spec for mDNS, but the main aim was to have my accessory appear in Homekit.