]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSPosix/ReadMe.txt
mDNSResponder-58.1.tar.gz
[apple/mdnsresponder.git] / mDNSPosix / ReadMe.txt
1 ReadMe About mDNSPosix
2 ----------------------
3
4 mDNSPosix is a port of Apple's core mDNS code to the Posix platform.
5 The sample shows how you might implement an mDNS responder inside an
6 embedded device, such as a printer or a web camera.
7
8 mDNS is short for "multicast DNS", which is a technology that allows you
9 to register IP services and browse the network for those services. For
10 more information about mDNS, see the mDNS web site.
11
12 <http://www.multicastdns.org/>
13
14 mDNS is part of a family of technologies developed by the IETF zeroconf
15 working group. For information about other zeroconf technologies, see
16 the zeroconf web site.
17
18 <http://www.zeroconf.org/>
19
20 Apple uses the brand name "Rendezvous" to describe our implementation of
21 zeroconf technologies. This sample is designed to show how easy it is
22 to make a device "Rendezvous compatible".
23
24 The code in this sample was compiled and tested on Mac OS X (10.1.x,
25 10.2), Solaris (SunOS 5.6), Linux (Redhat 2.4.9-21), and OpenBSD (2.9).
26 YMMV.
27
28 IMPORTANT
29 This sample is not a full port of Apple's Rendezvous APIs to Posix.
30 Specifically, the sample includes a responder daemon that registers
31 entities based on its command line arguments (or a text file). This is
32 perfect for a embedded device, but is not suitable for a general purpose
33 computer. A real implementation of the Rendezvous APIs would require a
34 mDNS daemon, client libraries that applications link with, and some form
35 of RPC between them. Client libraries and client-to-daemon RPC are
36 beyond the scope of this sample, however, this would be a good place to
37 start if you were interested in implementing these facilities on your
38 platform.
39
40
41 Packing List
42 ------------
43 The sample includes the following files and directories:
44
45 o ReadMe.txt -- This file.
46
47 o mDNSCore -- A directory containing the core mDNS code. This code is
48 written in pure ANSI C and has proved to be very portable.
49
50 o mDNSPosix.h -- The interface to the platform support code.
51
52 o mDNSPosix.c -- The platform support code for the Posix platform.
53 This code glues the mDNS core to Posix.
54
55 o mDNSUNP.h -- Interface to the code in "mDNSUNP.c".
56
57 o mDNSUNP.c -- A few routines from the "Unix Network Programming" book
58 that I borrowed to make the port easier. The routines are slightly
59 modified from the originals to meet my specific needs. You can get the
60 originals at the URL below.
61
62 <http://www.kohala.com/start/unpv12e.html>
63
64 o Client.c -- The main program for the sample mDNS client.
65
66 o Responder.c -- The main program for the sample mDNS responder.
67
68 o Services.txt -- A sample configuration file for the mDNS responder.
69 You can test with this file using the option "-f Services.txt".
70
71 o ProxyResponder.c -- Another sample mDNS responder, this one intended
72 for creating proxy registrations for other network devices that don't
73 have their own mDNS responders.
74
75 o ExampleClientApp.h
76 o ExampleClientApp.c -- shared code prioviding the
77 "ExampleClientEventLoop" used by Client.c and ProxyResponder.c.
78
79 o Makefile -- A makefile for building on Mac OS X and other platforms.
80
81
82 Building the Sample
83 -------------------
84 The sample does not use autoconf technology, primarily because I didn't
85 want to delay shipping while I learnt how to use it. Thus the code
86 builds using a very simple make file. To build the sample you should
87 type "make os=myos", e.g.
88
89 make os=osx
90
91 For Linux you would change that to:
92
93 make os=linux
94
95 There are definitions for each of the platforms I ported to. If you're
96 porting to any other platform you'll have to add appropriate definitions
97 for it.
98
99
100 Using the Sample
101 ----------------
102 Once you've built the sample you can test it by first running the
103 client, as shown below.
104
105 quinn% build/mDNSClientPosix
106 Hit ^C when you're bored waiting for responses.
107
108 By default the client starts a search for AppleShare servers and then
109 sits and waits, printing a message when services appear and disappear.
110
111 To continue with the test you should start the responder in another
112 shell window.
113
114 quinn% build/mDNSResponderPosix -n Foo
115
116 This will start the responder and tell it to advertise a AppleShare
117 service "Foo". In the client window you will see the client print out
118 the following as the service shows up on the network.
119
120 quinn% build/mDNSClientPosix
121 Hit ^C when you're bored waiting for responses.
122 *** Found name = 'Foo', type = '_afpovertcp._tcp.', domain = 'local.'
123
124 Back in the responder window you can quit the responder cleanly using
125 SIGINT (typically ^C).
126
127 quinn% build/mDNSResponderPosix -n Foo
128 ^C
129 quinn%
130
131 As the responder quits it will multicast that the "Foo" service is
132 disappearing and the client will see that notification and print a
133 message to that effect (shown below). Finally, when you're done with
134 the client you can use SIGINT to quit it.
135
136 quinn% build/mDNSClientPosix
137 Hit ^C when you're bored waiting for responses.
138 *** Found name = 'Foo', type = '_afpovertcp._tcp.', domain = 'local.'
139 *** Lost name = 'Foo', type = '_afpovertcp._tcp.', domain = 'local.'
140 ^C
141 quinn%
142
143 If things don't work, try starting each program in verbose mode (using
144 the "-v 1" option, or very verbose mode with "-v 2") to see if there's
145 an obvious cause.
146
147 That's it for the core functionality. Each program supports a variety
148 of other options. For example, you can advertise and browse for a
149 different service type using the "-t type" option. Use the "-?" option
150 on each program for more user-level information.
151
152
153 How It Works
154 ------------
155 A typical mDNS program is divided into three sections.
156
157 +----------------+
158 | Application |
159 +----------------+
160 | mDNS Core |
161 +----------------+
162 | Posix Platform |
163 +----------------+
164
165 The mDNS core code comprises the files in the "mDNSCore" directory.
166 It's standard ANSI C that's very portable. It relies on the underlying
167 platform code for all external functionality.
168
169 In this example the external platform code glues the mDNS core to a
170 POSIX-ish platform. This code is contained in the files:
171
172 o mDNSPosix.h
173 o mDNSPosix.c
174 o mDNSUNP.h
175 o mDNSUNP.c
176
177 The guts of the code is in "mDNSPosix.c".
178
179 I should be clear that true POSIX isn't powerful enough to accomplish
180 the job, so this code doesn't compile with _POSIX_SOURCE defined and
181 there's a bunch of conditional code that does different things on
182 different Unixen. I've isolated the hairiest parts of this code in the
183 "mDNSUNP".
184
185 Above the mDNS core code is the code that actually does
186 application-specific tasks. In this example I've supplied two
187 application programs: the responder (Responder.c) acts as a simple mDNS
188 responder, listening for mDNS service lookup requests and answering
189 them, and the client (Client.c), which is a simple mDNS browser, making
190 simple mDNS search queries. Both programs use the same mDNS core and
191 Posix platform code.
192
193 A discussion of the mDNS protocol itself is beyond the scope of this
194 sample. Quite frankly, my goal here was to demonstrate how it easy it
195 is to use Apple's mDNS core without actually understanding mDNS, and
196 because I achieved that goal I never had to learn a lot about how the
197 mDNS core code works. It's just a black box that I call. If you want
198 to learn more about mDNS, see the references at the top of this file.
199
200 The mDNS Posix platform code is actually pretty simple. mDNS core
201 requires six key features in its platform support.
202
203 o the core calls the platformm at startup (mDNSPlatformInit)
204 and shutdown (mDNSPlatformClose)
205
206 o the core calls the platform to send a UDP packet (mDNSPlatformSendUDP)
207
208 o the core calls the platform to set a timer (mDNSPlatformScheduleTask)
209
210 o the platform calls the core (mDNSCoreTask) when the timer expires
211
212 o the platform calls the core (mDNSCoreReceive) when a UDP datagram arrives
213
214 o the platform calls the core when network interfaces are
215 added (mDNS_RegisterInterface) or removed (mDNS_DeregisterInterface)
216
217 All of these features are implemented in "mDNSPosix.c".
218
219 The runtime behaviour of the code is as follows.
220
221 1. The application calls mDNS_Init, which in turns calls the platform
222 (mDNSPlatformInit).
223
224 2. mDNSPlatformInit gets a list of interfaces (get_ifi_info) and registers
225 each one with the core (mDNS_RegisterInterface). For each interface
226 it also creates a multicast socket (SetupSocket).
227
228 3. The application then calls select() repeatedly to handle file descriptor
229 events. Before calling select() each time, the application calls
230 mDNSPosixGetFDSet() to give mDNSPosix.c a chance to add its own file
231 descriptors to the set, and then after select() returns, it calls
232 mDNSPosixProcessFDSet() to give mDNSPosix.c a chance to receive and
233 process any packets that may have arrived.
234
235 4. When the core needs to send a UDP packet it calls
236 mDNSPlatformSendUDP. That routines finds the interface that
237 corresponds to the source address requested by the core, and
238 sends the datagram using the UDP socket created for the
239 interface. If the socket is flow send-side controlled it just
240 drops the packet.
241
242 5. When SocketDataReady runs it uses a complex routine,
243 "recvfrom_flags", to actually receive the packet. This is required
244 because the core needs information about the packet that is
245 only available via the "recvmsg" call, and that call is complex
246 to implement in a portable way. I got my implementation of
247 "recvfrom_flags" from Stevens' "UNIX Network Programming", but
248 I had to modify it further to work with Linux.
249
250 One thing to note is that the Posix platform code is very deliberately
251 not multi-threaded. I do everything from a main loop that calls
252 "select()". This is good because it avoids all the problems that often
253 accompany multi-threaded code. If you decide to use threads in your
254 platform, you will have to implement the mDNSPlatformLock() and
255 mDNSPlatformUnlock() calls which are no-ops in mDNSPosix.c.
256
257
258 Caveats
259 -------
260 Currently the program uses a simple make file.
261
262 There are various problems with loopback-only self discovery. The code
263 will attempt service discovery on the loopback interface only if no
264 other interfaces are available. However, this exposes a number of
265 problems with the underlying network stack (at least on Mac OS X).
266
267 o On Mac OS X 10.1.x the code fails to start on the loopback interface
268 because the IP_ADD_MEMBERSHIP option returns ENOBUFS.
269
270 o On Mac OS X 10.2 the loopback-only case fails because
271 mDNSPlatformSendUDP's call to "sendto" fails with error EHOSTUNREACH
272 [Radar ID 3016042].
273
274 I haven't been able to test the loopback-only case on other platforms
275 because I don't have access to the physical machine.
276
277
278 Licencing
279 ---------
280 This code is distributed under the Apple Public Source License.
281 Information about the licence is included at the top of each source file.
282
283
284 Credits and Version History
285 ---------------------------
286 If you find any problems with this sample, mail <dts@apple.com> and I
287 will try to fix them up.
288
289 1.0a1 (Jul 2002) was a prerelease version that was distributed
290 internally at Apple.
291
292 1.0a2 (Jul 2002) was a prerelease version that was distributed
293 internally at Apple.
294
295 1.0a3 (Aug 2002) was the first shipping version. The core mDNS code is
296 the code from Mac OS 10.2 (Jaguar) GM.
297
298 Share and Enjoy
299
300 Apple Developer Technical Support
301 Networking, Communications, Hardware
302
303 6 Aug 2002
304
305
306 To Do List
307 ----------
308 ¥ port to a System V that's not Solaris
309 ¥ use sig_atomic_t for signal to main thread flags
310 ¥ test and debug the daemon function, including properly logging