ZeroConf/Bonjour Library

Status
Not open for further replies.

Headroom

Well-known member
This library implements Apples implementation of ZeroConf Networking called Bonjour.
It was initially written in 2010 by Georg Kaindl and is still available in its original form
here.
As DHCP and DNS we're required for it to work but not part of the Arduino libraries before 1.0 the original library included implementations of these as well.

I've used it for about 2 Years now. DNS and DHCP are part of the Arduino Ethernet library since vision 1.0 so these part of the library were not needed anymore and I've been able to transition it from the Teensy++2 connected to a W5100 based WIZ812MJ Ethernet Module to the Teensy3 connected to a W5200 based WIZ820io Ethernet module.

Paul has voiced interest to make it part of Teensyduino so I've started adapting it so it can be used with the new auto detect (W5100 or W5200 Ethernet chip) Ethernet Library in Teensyduino 1.17 Release Candidate #1

I've been able to get it to work on the Teensy3 with the WIZ820io tonight and will continue my efforts with a Teensy++2 and WIZ820io and perhaps WIZ812MJ.
 
Last edited:
Very interested. I've got a board that can use either the WIZ820io, WIZ812mj, or CC3000, and the Bonjour library would be a nice addition to my code.
 
I should work already with Teensy3 and WIZ820ip and WIZ812MJ. I need to greenwire my Teensy++2 adapter boards for these WIZ820io Ethernet Module (does not have a connection reset line) to get it to work with the library. Once I've verified that that works I'll post a link.

However, getting it to work with the CC3000 would be nice but will require quite a bit of work. The Bonjour library uses direct hardware access by using definitions/functions provided the W5100. and W5200.cpp in the /utility folder in the Ethernet library that write directly into the W5100/W5200 registers.
It would be ibteresting to make the Bonjour library hardware independent.
 
Well..let me put it this way. I know what parts of the code would have to be touched/changed/replaced but I don't have an idea yet how to do that. But, one step at a time. I don't have a timeline but would guess that making it hardware independent will not happen for Teensyduino 1.17 if I have to figure out how to do al of that on my own ;-)

Zeroconf/Bonjour is based on mDNS (multicast DNS), which uses uses IP multicast User Datagram Protocol (UDP) packets. There is a very nice Wikipedia Article explaning some of that.
 
Last edited:
I'm looking at the EthernetBonjour code from gkaindl.com.

Code in EthernetBonjour/utility/EthernetCompat.cpp definitely talks directly to the hardware. It has hard-coded AVR register access for the SS signal that doesn't match to any Teensy board.

To make this hardware independent, I believe EthernetBonjour.begin() is going to need to be modified to take a reference to a Udp object. Internally, EthernetBonjour.cpp makes 53 calls to the ethernet_compat_XYZ functions. All need to be replaced with the higher level UDP functionality. Most of them look pretty simple, with direct replacements available from the Udp base class.

The one big problem I see is enabling multicast mode. It's currently done at line 288:

Code:
   ethernet_compat_write_SnDIPR(this->_socket, mdnsMulticastIPAddr);
   ethernet_compat_write_SnDPORT(this->_socket, port);

   if (ethernet_compat_socket(this->_socket, ECSnMrUDP, MDNS_SERVER_PORT, ECSnMrMulticast) < 0)
      return 0;
 
Please post a copy here on the forum, which is known to work with a Teensy and a Wiz812. If it runs on my hardware and discovers some Apple devices on my network, then I'll take a first pass at hacking the code.

Edit: looks like this Arduino forum topic has the needed multicast code.
 
Last edited:
How about a Teensy3 with a WIZ802io on Frankie, my Frankenduino board.
that one's working with service registration (_osc Open Sound Control) already and would include "your hardware" ;-)

I have not used the service discovery yet.
 
Regarding ZerConf/Bonjour on the CC3000 - the module library already supports this (albeit poorly) with the mdnsAdvertiser() API. This is actually what the CC3000 uses internally for its "Smart Config", see http://processors.wiki.ti.com/index.php/CC3000_mDNS and http://processors.wiki.ti.com/index.php/CC3000_Smart_Config for more details.

As of firmware 1.24 (the most current) there's still a bug with this function where it returns what you named the CC3000 as a service, but uses "target.local" as the device name. This thread on the TI forum goes into the problem in great detail:

http://e2e.ti.com/support/low_power_rf/f/851/t/290584.aspx

The short version of the story is TI admits the bug is there and will try to fix it in a future firmware but has no ETA on a fix.

In the meantime I've been working on my own CC3000 webserver/DNS responder and, while my code isn't ready to be published, this works:

1. Open & bind a UDP socket on port 4343 / IP 224.0.0.251, listen for requests
2. Parse any incoming packets, if they're queries for us then send a UDP mDNS reply with our info

If/when TI ever fixes their code, step 2 may be simplified to "if they're queries for us then call the CC3000 API function mdnsAdvertiser()" or if TI is really generous then 1&2 will become "periodically call mdnsAdvertiser()".

The downside to all of this is the ZeroConf/Bonjour only kind of works for name resolution. I have no problems with going to my Teensy3+CC3000 webserver "http://myteensy.local" on an iPhone, iPad, and Mac Mini on WiFi, but it doesn't work on my wired iMac because my Verizon router doesn't forward Bonjour between segments. It only works on Win XP, 7, or 8 if Bonjour is installed, and doesn't work on Android at all because it doesn't support mDNS (http://rgladwell.wordpress.com/2010/04/18/gotchas-android-and-multicast-dns/ et al).

tl;dr: in an all-Apple all-WiFi world you'll be able to get to your CC3000 device via name resolution, but so far supporting everything everywhere remains elusive.
 
@Paul,
OK. deal. I appreciate you even giving it consideration! I'll see that I get the other examples including service discovery to work and then post it. Thanks for posting the link to the Arduino thread with the mDNS code. I have to admit that with my limited programming knowledge some of this is clearly beyond my skill level. But it's a great learning experience.

@potatotron,
It would be great if we could combine efforts even though, as I've mentioned above my programming experience is rather limited. I've given up trying to "support everything everywhere". It is a sad and narrow minded story that Windows still does not support Bonjour but I can live with that for now. One step at a time. Let's get this " bonjour thing" done first.
 
Looks like Adafruit's CC3000 library does not support the hardware-independent APIs defined by Arduino.

To make a truly independent library will require modifying code in 4 places.

1: add beginMulti() to Arduino's API. I can do this, probably not in time for 1.17, but likely in 1.18.

2: modify Ethernet to provide beginMulti().

3: redesign the Bonjour library to use the hardware independent API.

4: add the Arduino API to CC3000. Whether Adafruit will accept this code is a good question?
 
Yes, mostly like that. Except it probably also needs a 3rd optional parameter in Udp.beginMulti() for the hardware address, since Bonjour seems to require that. Also except for the modern version of Ethernet which now includes UDP, rather than that out-of-date stuff where it was separate. beginMulti() also needs to be added at the base class level, not just the Ethernet library level, if it'll ever facilitate a library that works across different hardware. Long term, that API change will need to be standardized by the Arduino Team, which is a long and (usually) difficult process.

That process isn't even going to start, at least by my hand, until you post your copy of the library that's been tested on any of the Teensy boards (Teensy++ 2.0 is fine) with the WIZ812MJ. If I can start with it running on hardware I've already build, I'll fiddle with the API level stuff.
 
Last edited:
&#55357;&#56842;The link provided HERE includes a zipped WIP version of the EthernetBonjour library with the mDNS (Service Registration) part working with a:

  • Teensy++2 and WIS812MJ on a original PJRC adapter.
  • Teensy3 and WIZ820io
with Arduino 1.0.5 and Teensyduino 1.17 RC 1.
Out of the box it compiles for a W5100 (WIZ812MJ) based Ethernet chip. If a W5200 chip is desired the #define W5200 in /utility/EthernetCompat.cpp has to be un-commented. The Ethernet library that ships with Teensyduino 1.17 RC1 auto detects the correct Ethernet chip (very nice!!!) and does not require any modification.

As hinted above I was only able to verify that the mDNS part - Service Registration with or without text record - works. I used a fresh Ardiuno 1.0.5 and Teensyduino 1.17 RC1 for this.
I have not been able to verify whether the DNS-SD (Service discovery) or the Host name resolution works. I suspected that I broke something in my attempt to make this work with Teensy boards, however, DNS-SD and Host resolution also does not appear to function on my network with a vanilla Arduino Uno (R2) and a original Arduino EthernetShield in Arduino 0022 with a unmodified EthernetBonjour library as found at gkaindl.com. The the original author mentions, the library compiles to quite a large chunk of compiled code and he developed it on an Arduino Mega in conjunction with a Arduino Ethernet Shield. So honestly I don't know why the DNS-SD does not work at least on my network even with the basic hardware and software set-up.
"Does not work" mean that the examples compile and function but the Service Discovery or Host Name Resolution do not return results and time out by design after 5 sec of searching.

As I had already somewhat altered and stripped the original version thus making it difficult to see what actual changes were applied, I started from scratch and downloaded a virgin copy from the original author and commented every change that I applied. That way changes are clearly visible, which may help integrating it more tightly into Teensyduino and perhaps making it Hardware independent.
 
Last edited:
I was asked to provide code that would work on Teensys. I did but no feedback was provided so I am bumping this.
 
O.K., I guess I'm confused...

I'm trying to make my TeensyNet project discoverable with avahi, so I threw together this quick test

Code:
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetBonjour.h>
#include <t3mac.h>

// Should restart Teensy 3.x, will also disconnect USB during restart

// From http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0337e/Cihcbadd.html
// Search for "0xE000ED0C"
// Original question http://forum.pjrc.com/threads/24304-_reboot_Teensyduino%28%29-vs-_restart_Teensyduino%28%29?p=35981#post35981

#define RESTART_ADDR       0xE000ED0C
#define READ_RESTART()     (*(volatile uint32_t *)RESTART_ADDR)
#define WRITE_RESTART(val) ((*(volatile uint32_t *)RESTART_ADDR) = (val))


void softReset()
{
  // 0000101111110100000000000000100
  // Assert [2]SYSRESETREQ
  WRITE_RESTART(0x5FA0004);
}  


void setup()
{
  while(!Serial);
  Serial.begin(115200);
  delay(3000);
  Serial.println("EthernetBonjour - Registering a service");
  Serial.println("Reading MAC from hardware...");

  Serial.println(F("Configuring IP"));

  // start the Ethernet:
  read_mac();
  
  print_mac();
  Serial.println();
  
  if(Ethernet.begin((uint8_t *) &mac) == 0) // use this for dhcp
  {
    Serial.println(F("Ethernet,begin() failed - Resetting TeensyNet"));
    delay(1000);
    softReset();
  }else{
    Serial.println(F("Ethernet,begin() success"));
    Serial.print(F("My IP address: "));
    Serial.println(Ethernet.localIP());
  }

// start Bonjour service
  if(EthernetBonjour.begin("TeensyNet"))
  {
    Serial.println(F("Bounjour Service started"));
    EthernetBonjour.addServiceRecord("TeensyNet._http", 80, MDNSServiceTCP);
  }else{
    Serial.println(F("Bounjour Service failed"));
  }
}

void loop()
{

// This actually runs the Bonjour module. YOU HAVE TO CALL THIS PERIODICALLY,
// OR NOTHING WILL WORK! Preferably, call it once per loop().

  EthernetBonjour.run();

}

which compiles and runs with the following in my serial debug terminal

Code:
EthernetBonjour - Registering a service
Reading MAC from hardware...
Configuring IP
04:E9:E5:00:41:3B
Ethernet,begin() success
My IP address: 192.168.1.23
Bounjour Service started

But when I go looking for the service using avahi-discover, there's noting about "TeensyNet" in the discovery window (I'm running Debian 7 on my workstation, btw)

Am I missing something simple??
 
Well...its not your code as that works. Just tried it out and the service registers correctly on my network:
Screen Shot 2014-01-27 at 8.23.13 PM.png

You may want to check out your routers configuration.
 
I have numerous other devices running Bonjour / avahi-daemon that work just fine, what router settings would affect just this? I use a WRT54GL

Here's a copy of my avahi-discover ouput:
avahi-discovery.png
 
If that's the case then network wise that should be fine. I will continue to investigate...

Edit: I think I have found "something". There are some changes in the Ethernet Library and SPI library from 1.17 to 1.18RC2 that I have to investigate. Got to go to work now but will continue tonight...
 
Last edited:
It compiles fine with Teensyduino 1.17 but not with Teensyduino 1.18 BECAUSE Teesnyduino 1.18 uses the new SPIFIFO methods.
I need to replicate some of that code in EthernetCompat.cpp, so hold on for a few days.

BTW this is exactly why I am hoping at some time to make this library hardware independent. I was hoping for some community support but there seems to be very low interest to say the least :/
 
All right! I pushed the library to my GitHub account: HERE

Now compatible with Teesnyduino RC1.18RC2

Tested it with your code and registered the TeensyNet HTTP(_tcp) service and then with my OSCuino test sketch on my iPhone, registering OSC (_udp) service. The new Ethernet SPIFFO routines seem to work fine wirelessly carrying UDP packets through my network.
 
Last edited:
Status
Not open for further replies.
Back
Top