You walk in a few minutes late to a meeting and want to know what you’ve missed. You open your text editor and your computer automatically discovers a shared document in which one or more attendees are taking notes. You have a couple of colleagues who are busy in another meeting but are interested in the topics being discussed in your meeting. You invite your colleagues to view the notes being taken and to contribute their comments and questions. A presenter announces that anyone wanting a copy of his slides should let him know. You open your local Instant Messenger application and see his name in the list of available names, even though you have never met before and he is not in your buddy list. A moment later, he has placed his presentation in your drop box in your Public folder, which he has discovered in his network directory.
The meeting comes to an end. Before anyone erases the whiteboard, someone snaps a quick picture or two and puts it in their photo-sharing library so that anyone interested can download it. You notice a new entry in your audio software that announces that the person who was recording the session has already posted it in her shared audio library. Before you save the notes on the session, you decide to print out a copy to read on the plane ride back. In the print dialog, you discover several printers and choose the one labeled “Third Floor Meeting Rooms.”
This is not a fantastical glimpse of the elusive future. It is a concrete description of what is available today using Zeroconf. In this chapter, you will get a quick overview of the various components that make up Zeroconf. In the following four chapters, these details will be fleshed out. The second half of this chapter examines the Zeroconf design principles that build on two decades of experience with the AppleTalk Name Binding Protocol.
None of the examples that took advantage of Zeroconf began with someone thinking, “You know what I could really use right now? An IP address.” Certainly, it’s a
rare person who takes the time to say, “Now that I have an IP address, I could use a friendly domain name. I should learn how to set up DNS on my laptop.” A typical user of Zeroconf should not be aware of the infrastructure required. She just wants to use a printer, stream music, exchange photos, or use some other service.
The architecture of Zeroconf is built around simplicity. It should be as easy for an end user to connect to a printer or locate streamed music as it is for him to turn on a light bulb. The simplicity extends to implementers as well. A vendor of an inexpensive device who desires to use Zeroconf should not find it hard to implement Zeroconf, even in devices with extremely limited memory capacity.
To the end user, the most important facet of Zeroconf is the ability to easily browse for available services. It is worth taking a moment to appreciate the significance of the concepts encapsulated in that short phrase. Start with these five highlighted words as the prime directive for Zeroconf.
With Zeroconf, you browse for services, not for hardware. The reason for this is simple but important: if you want to print, there is little benefit to discovering hardware that doesn’t do printing. Similarly, there is little benefit to discovering things that are printers but speak only a printing protocol that your client does not support, since you wouldn’t be able to use those printers. Conversely, suppose that there is a device on the network in a legal office that functions, protocol-wise, as a printer, but instead of printing on paper, it archives documents as date-stamped PDF files on recordable CDs. You would want your printing client to discover this service, since it’s a service your printing client can use. Suppose there were an inexpensive USB printer (which doesn’t have Postscript or networking) connected to a desktop computer (which does), with software making Postscript printing service available to other machines on the network via IPP (Internet Printing Protocol). You would want your Postscript IPP printing client to discover this service, since it’s a service you can use. What is it that your printing client is discovering, in this case? The USB printer? The desktop computer? The software? No. The insight here is to realize that what your printing client is discovering is the aggregate service offered by the computer, the printer, and the software working in concert, and it is that aggregate service that is being advertised as a logical entity on the network in its own right. The USB printer could break and be replaced, and the logical service being offered would remain the same. The desktop computer could break and be replaced, and the logical service being offered would remain the same. Even the software could be upgraded or replaced, while the logical Postscript IPP printing service being offered to network clients would remain unchanged. The important principle here is that when you’re looking for services on the network, the relevant question is not “What are you?” or even “What do you do?” but “Do you speak my language?”
The list that the user gets should be services that are currently available to them. They should be able to see the list of currently available printers, select one, and use it. As with all such network protocol designs, there is a trade-off between timeliness of information and network efficiency. Continuously querying the network to find what services are available gives accurate, up-to-date information but can impose an unreasonable burden on the network. Querying the network just once is much more efficient, but the client’s information soon gets out of date, necessitating a “refresh” button in the UI, which then puts the burden on the human user to keep clicking the refresh button (which puts a burden on the network). Zeroconf solves these problems using a variety of techniques. For efficiency, clients query the network infrequently, as little as once per hour. To avoid long delays before new services are discovered, when a service starts up it sends a few multicast announcement packets, so clients become aware of the new service even before performing their next scheduled query. IP Multicast addresses are special destination addresses that cause packets to be delivered to all interested parties on the local network, rather than just to a single machine. When services go away, they send multicast “goodbye” packets, so they are promptly removed from all clients’ UI lists. In the event that a service is unceremoniously disconnected without getting a chance to send its “goodbye” packet, stale data may remain in lists for a while, but even this case is handled by Zeroconf. When a client attempts to contact a stale service that is no longer present, the failure is noted, and the service is promptly removed from the list of available services. This prompt removal occurs not only on the client that directly experienced the failure but also on all the other clients on the same network link, which passively observe the failure and update their own lists too. Zeroconf uses these and a variety of other techniques to provide timely, accurate information while keeping the network traffic to a minimum.
This kind of peer-to-peer, multicast-based protocol is great for small networks because it is very reliable and requires no dedicated service-discovery infrastructure, but no matter how efficient the protocol, there will come a network size where it no longer makes sense. In an organization with thousands of machines, having every single machine multicasting to every other machine all the time would not be reasonable. Beyond a certain size, every service-discovery protocol has to transition from using peer-to-peer multicast to some kind of centralized repository to hold service information. Services and clients communicate with the centralized repository using a wide-area protocol. In Zeroconf, the centralized repository is one that most companies already have—a DNS server—and the wide-area protocol is the standard DNS protocol with two small extensions, Update Leases and Long-Lived Queries. Update Leases allow a DNS server to expire server records if the service that created them crashes, and Long-Lived Queries allow a client to be notified as services come and go, rather than having to keep polling the server to find out what’s new.
Zeroconf would never have been so widely adopted if using it required popping
open a terminal window and typing in obscure commands. Command-line tools are
great for developers and network administrators, but end users will be browsing
for services within a context. They are not conscious that they are requesting a
list of services that implement a protocol. For example, when running iTunes,
users simply see a list called “Shared Music.” They don’t need to be aware that
iTunes is performing a query for Zeroconf service type
_daap._tcp to find the list of local servers offering the Digital
Audio Access Protocol (DAAP) service.
Another thing you’ll notice is that the names of shared music sources displayed in iTunes don’t need to look like "http://thing.company.com,” all lowercase with no spaces or other punctuation. In the example at the beginning of this chapter, the printer was named “Third Floor Meeting Rooms,” not "http://f3mr.company.com.” In command-line user interfaces, you want names to be short and quick to type. In graphical user interfaces, you don’t need to type names because you just select them from a list of choices, so they can be long and descriptive and can contain rich punctuation, accented letters, and non-roman characters, such as Kanji.
Although service discovery is the most visible element of Zeroconf, Zeroconf is more than just that. Zeroconf is a three-layer foundation for IP networking, with service discovery sitting atop the two lower layers, addressing and naming.
The first requirement for IP networking is an IP address. There are existing mechanisms for IPv4 address allocation, such as using manual configuration or a DHCP server, but when neither of these is available, Zeroconf-capable devices will use a self-assigned IPv4 link-local address instead. In brief, the mechanism behind self-assigned addresses is that the device selects an address at random within a prescribed range, sends some ARP requests, and then, if no answers are received, proceeds to use that address. Self-assigned IPv4 link-local addresses are discussed in detail in Chapter 2. IPv6 also has self-assigned link-local addresses, though sadly, at the present time—even though Mac OS X, Windows, and Linux all support IPv6—most of the low-cost peripherals that they talk to, such as printers and cameras, don’t yet support IPv6.
The second requirement is that the typical usage model for IP networking expects hosts to have names, not just numerical addresses. Having to remember and type numerical addresses is cumbersome at best, and when the addresses are being picked randomly, it may not even be possible. We need a way to associate a stable name with each device, in order to determine what address it has picked for itself, at this instant. The Internet’s existing mechanism for associating names with addresses is a DNS server, but when no DNS server is available, Zeroconf-capable devices will use Multicast DNS (mDNS) to achieve substantially the same effect on the local link, without having to set up and maintain a dedicated DNS server. In brief, the mechanism behind mDNS names is very similar to self-assigned addresses: the device sends a few mDNS queries for its desired name, and if no answers are received, the device can then use that name. Multicast DNS naming is discussed in detail in Chapter 3.
At the end of any software engineering effort, the developers have a deep understanding of the problem they were solving. Imagine how much better the finished product would be if they had time to start over with the benefit of the experience they have gained. The DNS Service Discovery (DNS-SD) layer of Zeroconf builds on years of experience with AppleTalk and its Name Binding Protocol (NBP) and improves on the earlier technology while building an all-IP solution.
AppleTalk NBP communicated the available services in a way that was logically consistent with an end user’s perspective. Additionally, NBP allowed users to perform an action using a connected device without needing to know the device’s address and without needing to become their own network administrator. Although DNS-SD is not simply a rewrite of AppleTalk NBP, there are many things that NBP got right, and DNS-SD brings those properties to IP networking.
In AppleTalk NBP, the primary named entity is not a piece of hardware or even a piece of software but a logical service with which you can communicate using a particular specified protocol. There is little benefit for the average user in being able to locate and connect to a device if she cannot communicate with it. The implication is that it is most useful to name entities with which you can communicate. DNS-SD maintains the same philosophy, naming logical services as the primary entity on the network. Continuing this philosophy further, it is important not only what the service does, in a human sense, but what network protocol it uses to do it, since there’s no use discovering it if your client can’t talk to it. For example, when you use a web browser to view a web site with the URL http://www.example.com, you generally do not know or care much which particular device is answering your request. What you care about is that it speaks Hypertext Transfer Protocol (HTTP), and that the content it sends you is something your web browser knows how to decode and display, typically Hyper Text Markup Language (HTML), and that the content relates to the http://example.com domain.
Suppose you are interested in locating web sites hosted on your local network. Suppose you could find the IP addresses of all nearby machines. Then what? You could try to contact them with your web browser using the well-known port 80. But it is certainly possible for a single device to host more than one web site, listening on different ports. What you really want is a different sort of browser that could locate all local services that offer HTML over HTTP. Zeroconf’s DNS-SD allows these services to advertise themselves as offering HTML over HTTP and provide their name, IP address, and port number.
Historically, Internet protocols have assumed so-called “well-known” port numbers. When you look up the address of http://www.example.com, the Domain Name System tells your computer the IP address of the machine to contact but not the TCP port number. The historical solution to this problem is that your web browser assumes that the desired web server must be listening on TCP port 80. If it’s not (e.g., because two web server processes are running on the same machine and they can’t both use the same TCP port), then blindly assuming TCP port 80 won’t work. You have to manually override the default port, as in http://www.example.com:1234. While that may superficially seem to work, it has problems. Once you’ve published that URL, if you change the port number the server is listening on, the URL will stop working. It’s fragile, like publishing a URL with a fixed dotted-decimal IP address embedded in it instead of a DNS name.
Another problem with “well-known” port numbers is that if every new protocol gets its own reserved number, we’re in danger of running out. You can see the currently assigned port numbers at http://www.iana.org/assignments/port-numbers. Thousands are already reserved for applications you will probably never run on your computer.
Zeroconf’s DNS-SD solves this problem by using DNS “SRV” records, which tell the client the service’s port number as well as its IP address, obviating the need for pre-allocated “well-known” port numbers. Any service can use any available port on your computer and advertise its port to prospective clients along with its IP address.
AppleTalk NBP has a mechanism for browsing the network for services, but, as its name emphasizes, it is primarily a Name Binding Protocol. Its primary function is binding human-meaningful names to computer-meaningful network addresses. A human user will use the browsing capabilities to locate a service initially, such as selecting a default printer, but every time the name service is used subsequently, the Name Binding Protocol is used to find out the current network address and port number for that service. This means that even if the printer address changes, clients will still be able to connect to it at the new address without disruption.
This late binding of a name to an address is an important feature of a technology intended to replace AppleTalk. If a service is available on a network that uses DHCP or link-local addressing, there is no guarantee that the device hosting the service will have a consistent IP address. When ports are allocated dynamically, there’s no guarantee the service will always be running on the same port. Late binding ensures that the client attempts to connect to the current IP address and port number.
Service requests consist of asking for a service of a particular type in a
particular domain. This builds on the AppleTalk convention of using names structured
Name: Type @ Zone. The
Zone in AppleTalk NBP corresponded to some logical grouping based on
location (“Third Floor”) or organizational classification (“Sales”). The equivalent
concept in DNS is a subdomain, such as http://sales.example.com or http://thirdfloor.example.com. These replacements for zones provide an
independent namespace so that there is no confusion in printers with the same name
that are located in different zones.
In AppleTalk NBP, the
Type identified the
protocol that the service speaks. So, for example, the NBP Service Type “LaserWriter”
denotes a service that speaks PostScript over AppleTalk Printer Access Protocol over
AppleTalk Transaction Protocol over AppleTalk Datagram Delivery Protocol. The
equivalent DNS-SD service type might be
which indicates a printer that speaks the Internet Printer Protocol (IPP) over TCP
Name portion should be a user-friendly
name. With this approach, the names are both long and descriptive. The end user will
be employing a browser of some sort to select named services from a list. As they
will not have to type the service name every time they want to use a service, the
names should not be cryptic for the sake of making them shorter. So, for example,
there could be a service with the full name
Meeting http://Rooms._ipp_tcp.examples.com . Notice that
the service name can contain spaces as well as dots, percent signs, and other
symbols. The character set is also not restricted to US-ASCII; users are free to
choose names using any legal Unicode characters.
When a device is first connected to a network, it must manually or automatically gather information about the local network. With mobile devices, this happens often enough that it is unreasonable to require that a human configure the device every time the device joins a new link. For example, where a site offers one or more DNS domains with services available for browsing, the device should be able to learn this from the network, rather than requiring it to be manually configured by the human user.
The list of services displayed in the browser should be dynamic. You have seen discovery mechanisms that use an icon or dialog to indicate that the list of services is being updated. After some unacceptably long delay, a static list of results is displayed. The only way to refresh this list is for the user to press a refresh button or for the client application to regularly poll for available services. In a Zeroconf-based service browser, less than a second elapses from the time that a user initiates browsing to when she is presented with a list of results. The browser will not burden the network with frequent polling for available services. The list will update to add or remove services based on announcements from the services, from non-renewed leases, and from multicast messages from other devices attempting to use a listed service.
Zero Configuration Networking—Bonjour, as Apple calls it—provides a three-layer foundation to enable hardware and software makers to produce great products. Zeroconf doesn’t do printing. Zeroconf doesn’t do network music. Zeroconf doesn’t do photo sharing or multiuser document editing or instant messaging. What Zeroconf does is provide the rock-solid foundation so that those great products can be built without worrying that, from time to time, TCP/IP might fall apart and let them down.
Chapter 2 describes the first layer of the three-layer foundation: getting an IP address when there’s no working DHCP server. Chapter 3 describes the second layer: being able to refer to hosts by name when there’s no working DNS server. Chapter 4 describes the third layer: discovering what’s available on the network without having to ask the person sitting next to you for help. Chapter 5 extends Chapter 4’s local service discovery out to the global Internet. The second half of the book, Chapters 6 and onward, presents the APIs in various different languages that allow you to use local- and wide-area service discovery in your hardware and software products.