Running my .Net Core mDNS service on Windows IoT

As part of my ongoing experiments with C# and mDNS (to build my own Homekit accessory), I got to the point where I wanted to run my code on a Raspberry Pi.

Microsoft have released a version of Windows 10 that will run on a Raspberry Pi in a headless mode. The main advantage of this is that it contains the .Net Core runtime!

To get started, download Microsoft IoT manage and fire it up. Under the menu, you’ll see an option to Set up a new device. This lets you flash an SD card with the code necessary.

iot flashing UI.PNG

iot flashing.PNG

Once the formatting and flashing is complete, you’ll have an SD card containing Windows IoT. Pop this into your Raspberry PI, and after a minute or five it will appear under the My devices view.

To get me started, I launched Remote Powershell. When it started, I got prompted for credentials.

iot powershell ip.PNG

This includes the IP Address and the account Administrator (the password for which, you set earlier). I found that this just didn’t work. I replaced the IP address with the machine name (minwinpc) and it worked!

iot powershell ip domain.PNG

I just realised this is a real Windows XP dialog!

After Powershell started, I opened a file share and created a directory called Climenole. To get my little Console app ready, I needed to compile it for ARM. Thankfully, this was straightforward. From the command prompted, I ran this command

dotnet publish -r win-arm

This compiles the app for the win-arm architecture. From the project directory, you can access


to see all the published files. I took all these files and copied them across to the Climenol directory I created on the Raspberry Pi.

Once the copy completed, I could run my app using Powershell.

iot wrong ip address.PNG

It didn’t work the first time as the hardcoded IP address wasn’t right, but after a tweak,

iot responding to packets.PNG

It started answering responses and even appeared in Homekit.


A good first step and proved that my mDNS was portable.

Next challenge is getting all the crypto code working, so that I can actually add and control the accessory from Homekit. It was a pain to get it working on the .Net Framework, so I suspect it will be no picnic on Core!

Update (07 Jan, 2019) I’ve had a couple of people ask to see the mDNS code. It’s up on Github –¬†


Apple Bonjour for .Net Core (Part 3)

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 –¬† – which seemed to describe the response format I was interested in.

wireshark txtwireshark details

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!

Wireshark no answers

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!

Wireshark Valid TXT record

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 ( 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!)

Wireshark single request no response

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!!

Looping back on itself

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:

Console single request single response

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 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 ( I copied the snipped of code, tweaked it a little and reran my test. Amazingly, it worked!

Wireshark single request single response

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!

Wireshark TXT response detail

Unfortunately, the mDNS Browser didn’t show anything.

mDNS No Services Found

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:

Wireshark HAP response

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.

Wireshark first response

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.

Wireshark local not a word

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

Wireshare showing pointers

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!

Wireshark - wrong port

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!

mDNS Service Found


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.


Apple Bonjour for .Net Core (Part 2)

In part 1, I wrote a simple Core console app that could log the multicast requests it received. Running the simple Bonjour Browser utility, I could see this being logged

The lines¬† _services_dns-sd seems to indicate some sort of services request being made, which made sense, given that Bonjour’s purpose for existing is to advertise services on a network. A quick Google for¬†_services_dns-sd lead me to this Apple article¬†

This confirmed my hunch.

¬†Devices running mDNSResponder-58.6 (Mac OS X 10.3.4) or later will respond to the “Service Type Enumeration” meta-query described in Section 10 of the¬†DNS-SD specification. Issuing a Multicast DNS PTR record query for the name “_services._dns-sd._udp.local.” will return a list of service types being advertised on the local network.

Aside from the full stops being displayed as question mark characters, this looked pretty sensible.

First order of business was to actually parse the byte[] into its parts and display them. Back to RFC 6762.

Section 18 talks about the message format, but deals a lot in bits, rather than bytes. To help me understand the values a bit better, I decided to write each request out as bits.

I got something like this (each byte in its own line)


I started by trying to compare each part to the corresponding bit outline in the RFC. Nothing matched, so I went back to Google and found this piece on Wikipedia ( A quick read and the first example looked like that I wanted.

00 00 Transaction ID
00 00 Flags
00 01 Number of questions
00 00 Number of answers
00 00 Number of authority resource records
00 00 Number of additional resource records
07 61 70 70 6c 65 74 76 “appletv”
05 6c 6f 63 61 6c “local”
00 Terminator
00 01 Type (A record)
00 01 Class

To confirm, I went back to my C# and modified it to show the data in a similar shape.

Working with the first 12 bytes, I saw this in the console’s output

00 00
00 00
00 01
00 00
00 00
00 00

This looked identical to the example in Wikipedia. I then went about look for the null terminator. After some tricking around I ended up with this

00 00 Transaction ID
00 00 Flags
00 01 Number of questions
00 00 Number of answers
00 00 Number of authority resource records
00 00 Number of additional resource records
09 5F 73 65 72 76 69 63 65 73 07 5F 64 6E 73 2D 73 64 04 5F 75 64 70 05 6C 6F 63 61 6C _services_dns-sd_udplocal
00 Terminator
00 0C Type
00 01 Class

This is a near perfect match to the Wikipedia entry. The primary difference is the “Type” value (and the actual request content (_services_dns instead of appletv.local)

Type value of 0x0C is obviously different, so I hit Google again and found this lovely Microsoft article.

It explains the various parts of the request/response and the 0C type is a PTR request. This seems appropriate for DNS service discovery! Huzzah.

Next step is to now respond with some data, probably in the form of a TXT record.


Apple Bonjour for .Net Core

As part of my work on building a .Net implementation of Apple Homekit protocol, I want to have it run on a Raspberry Pi. My plan is to accomplish this using Windows 10 for IoT. This is basically a cut down version of Windows 10, designed to run .Net Core and UWP apps. I haven’t really explored it very much, but it seems to suit my needs. I can deploy my Homekit service and put the Raspberry Pi in the cupboard.

The first piece of functionality I need for my Homekit implementation is the broadcasting of the accessories using Bonjour. Bonjour is apple’s zero configuration protocol implementation. It is available on Windows, via Apple’s SDK, but unfortunately, it’s a COM component, so running it on Raspberry Pi is a non-starter. I searched around on the internet for a few hours and discovered, to my immense disappointment, that there are no Nuget packages for advertising services over Bonjour. Lots of ones for browsing and searching, but none for advertising.

These kind of situations, whilst annoying, do provide an opportunity to learn something new. What would it take to create a simple implementation of Bonjour that would run on .Net Core, on a Raspberry Pi. Let’s find out ūüôā

To get the ball rolling, I created a .Net Core console application in Visual Studio. This doesn’t achieve anything in and of itself, but makes me feel like I’m making progress ūüôā

A read through a few articles on Bonjour;

and I was ready to start. General searching around the web, led me to RFC-6762 (, which describes Multicast DNS or mDNS. This is used by Bonjour. I do love a good RFC.

After reading the first few pages, I established the following facts; mDNS, in essence, works by resolving .local addresses e.g. computer.local or hap.local. It does this by sending requests over multicast to the group on the port 5353. I had come across the multicast technology (my router didn’t support it) a few years ago, so I was familiar with the main concepts.

Converting this into code, I came up with

public void Start()
 UdpClient udpClient = new UdpClient();

udpClient.ExclusiveAddressUse = false;
 IPEndPoint localEndpoint = new IPEndPoint(IPAddress.Any, 5353);

udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
 udpClient.ExclusiveAddressUse = false;


IPAddress multicastaddress = IPAddress.Parse("");

while (true)
 Byte[] data = udpClient.Receive(ref localEndpoint);
 string dataAsString = Encoding.UTF8.GetString(data);
 catch (Exception exp)

This code essentially listens on port 5353 for broadcasts to the group

When I fire up the console app, I just see this


Not much to see. In order to generate some Bonjour traffic, I use an app called Bonjour Browser

I launch this and again, I don’t see much:


However, a few lines appear in my console app:

Console with data

Right now I don’t have a clue what these are, but I can see what might be dns requests.

More detail to follow!


Rebuilding CommuterPal with Azure Functions and CosmosDB

A few years ago I built an iOS called Commuter Pal. I never actually launched the app, since I tried to do *way* too much in terms of route planning and intelligent alerting. Since I didn’t actually commute myself, it was not something I could field test.

Fast forward to 2017 and I’ve been commuting for about six months now. I’ve tried a few different apps to help keep me ahead of delays, but most of the apps are aimed at the entire network and have loads of bells and whistles, so I gave up using them as they just didn’t help. Most of the time I’m already on the platform before I learn of a signal failure or ill passenger.

To coincide with the fact I’ve started wearing my Apple Watch again, I’ve decided to try and bring Commuter Pal back to life with a more simple goal; a watch complication that tells me if my route is clear or blocked.

My choice of tech is predictable – iOS (Objective-C) and .Net. This time, instead of my usual WebAPI approach, I’m going to try and build the whole thing with CosmosDB and Azure Functions. I’m not really sure how it will work, but I think that all phone interactions can be powered by HTTP bound Functions and calls to TFL for updates can be done using Timer based Functions. Throw in a queue here or there and an Azure Notification hub and we should be in business.

I’ll try and document the process as I go along.

If you’re an iOS user and commute using the London Underground, I’ll be making this app available for beta testing, so if you’re interested in taking a look, let me know!

Roomr 4.1 – Search has arrived!

I’ve just submitted Roomr 4.1 to the App Store for approval. This version brings my first attempt at a search feature.

A few weeks back I was contacted by a user in the Netherlands, who wanted to use Roomr to improve the way they booking parking spaces at their company. They had an existing Exchange installation that used individual calendars for individual parking spaces. The then grouped this parking spaces into buildings using Room Lists. They found that searching and booking was quite difficult from Outlook.

Search was something that has been on the Roomr roadmap for quite some time, but I never got around to implementing it, simply because Exchange’s API don’t really allow for a general search. However,¬†¬†with this request focused on Room Lists, I had a very clear requirement to work with.

After a few rounds of beta testing, I’m pleased to report that I have submitted Roomr 4.1 to Apple!

Simulator Screen Shot 23 Mar 2017, 13.23.24

This search UI allows you to choose a Room List, date and a time range. All the rooms contained with the Room List are checked for availability. Once a match is found, the user can choose one of the rooms and open its calendar. As a shortcut, the date & time they searched for will be displayed within the calendar.

Simulator Screen Shot 23 Mar 2017, 14.59.38.

Booking then works as normal.

This Search¬†feature is also available with G Suite, so Google users haven’t been left out. It obviously¬†doesn’t rely on¬†Room Lists. Instead, all rooms with¬†the domain’s Resources are searched to see if they are free at the specified time.

Roomr 4.1 should be available to buy from the App Store in the next couple of days.

Azure Functions and ServiceBus gotcha

Okay, so this might not be a gotcha, but I lost an hour early this morning trying to diagnose a problem with an Azure Function I’m writing. I’m using ServiceBus triggers and outputs to form a processing pipeline using the functions. One function reads the messages on a queue and then puts another message on a queue for another function to handle.

I was getting this non descriptive error when running locally.


After much experimentation I realised that the ServiceBus queue in the function.json must actually exist ūüôā For some reason I assumed the host would create them as required! Anyway.

Might be of use to somebody else.