• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- Mode: C; tab-width: 4 -*-
2  *
3  * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16 
17  *
18  * NOTE:
19  *
20  * These .Net APIs are a work in progress, currently being discussed and refined.
21  * If you plan to build an application based on these APIs, you may wish to
22  * statically link this code into your application, or otherwise distribute
23  * the DLL so that it installs into the same folder as your application
24  * (not into any common system area where it might interfere with other
25  * applications using a future completed version of these APIs).
26  * If you plan to do this, please be sure to inform us by sending email
27  * to bonjour@apple.com to let us know.
28  * You may want to discuss what you're doing on the Bonjour mailing
29  * list to see if others in similar positions have any suggestions for you:
30  *
31  * <http://lists.apple.com/bonjour-dev/>
32  *
33  */
34 
35 #pragma once
36 
37 #include <dns_sd.h>
38 #include <vcclr.h>
39 #include <memory>
40 #include <winsock2.h>
41 
42 using namespace System;
43 using namespace System::Net;
44 using namespace System::Runtime::InteropServices;
45 using namespace System::Threading;
46 using namespace System::Collections;
47 
48 
49 namespace Apple
50 {
51 	namespace DNSSD
52 	{
53 		public __gc class ServiceRef;
54 
55 		public __value enum ServiceFlags : int
56 		{
57 			MoreComing			=	1,
58 			/* MoreComing indicates to a callback that at least one more result is
59 				* queued and will be delivered following immediately after this one.
60 				* Applications should not update their UI to display browse
61 				* results when the MoreComing flag is set, because this would
62 				* result in a great deal of ugly flickering on the screen.
63 				* Applications should instead wait until until MoreComing is not set,
64 				* and then update their UI.
65 				* When MoreComing is not set, that doesn't mean there will be no more
66 				* answers EVER, just that there are no more answers immediately
67 				* available right now at this instant. If more answers become available
68 				* in the future they will be delivered as usual.
69 				*/
70 
71 			Add					=	2,
72 			Default				=	4,
73 			/* Flags for domain enumeration and browse/query reply callbacks.
74 				* "Default" applies only to enumeration and is only valid in
75 				* conjuction with "Add".  An enumeration callback with the "Add"
76 				* flag NOT set indicates a "Remove", i.e. the domain is no longer
77 				* valid.
78 				*/
79 
80 			NoAutoRename		=	8,
81 			/* Flag for specifying renaming behavior on name conflict when registering
82 				* non-shared records. By default, name conflicts are automatically handled
83 				* by renaming the service.  NoAutoRename overrides this behavior - with this
84 				* flag set, name conflicts will result in a callback.  The NoAutorename flag
85 				* is only valid if a name is explicitly specified when registering a service
86 				* (i.e. the default name is not used.)
87 				*/
88 
89 			Shared				=	16,
90 			Unique				=	32,
91 			/* Flag for registering individual records on a connected
92 				* DNSServiceRef.  Shared indicates that there may be multiple records
93 				* with this name on the network (e.g. PTR records).  Unique indicates that
94 	the
95 				* record's name is to be unique on the network (e.g. SRV records).
96 				*/
97 
98 			BrowseDomains		=	64,
99 			RegistrationDomains	=	128,
100 			/* Flags for specifying domain enumeration type in DNSServiceEnumerateDomain
101 	s.
102 				* BrowseDomains enumerates domains recommended for browsing, RegistrationDo
103 	mains
104 				* enumerates domains recommended for registration.
105 				*/
106 		};
107 
108 
109 		public __value enum ErrorCode : int
110 		{
111 			NoError				=	0,
112 			Unknown				=	-65537,
113 			NoSuchName			=	-65538,
114 			NoMemory			=	-65539,
115 			BadParam			=	-65540,
116 			BadReference		=	-65541,
117 			BadState			=	-65542,
118 			BadFlags			=	-65543,
119 			Unsupported			=	-65544,
120 			AlreadyRegistered	=	-65547,
121 			NameConflict		=	-65548,
122 			Invalid				=	-65549,
123 			Incompatible		=	-65551,
124 			BadinterfaceIndex	=	-65552
125 
126 			/*
127 				* mDNS Error codes are in the range
128 				* FFFE FF00 (-65792) to FFFE FFFF (-65537)
129 				*/
130 		};
131 
132 		public __gc class DNSServiceException
133 		:
134 			public Exception
135 		{
136 		public:
137 
138 			DNSServiceException
139 				(
140 				int err
141 				);
142 
143 			DNSServiceException
144 				(
145 				String				*	message,
146 				System::Exception	*	innerException
147 				);
148 
149 			int err;
150 		};
151 
152 
153 		/*
154 		* class RecordRef
155 		*
156 		* This is a thin MC++ class facade on top of a DNSRecordRef
157 		*/
158 		public __gc class RecordRef
159 		{
160 		public:
161 
RecordRef()162 			RecordRef()
163 			{
164 				m_impl = new RecordRefImpl;
165 				m_impl->m_ref = NULL;
166 			}
167 
~RecordRef()168 			~RecordRef()
169 			{
170 				delete m_impl;
171 			}
172 
173 			__nogc class RecordRefImpl
174 			{
175 			public:
176 
177 				DNSRecordRef m_ref;
178 			};
179 
180 			RecordRefImpl * m_impl;
181 		};
182 
183 
184 		/*
185 		* class ServiceRef
186 		*
187 		* This is a thin MC++ class facade on top of a DNSServiceRef
188 		*/
189 		public __gc class ServiceRef : public IDisposable
190 		{
191 		public:
192 
193 			ServiceRef(Object * callback);
194 
195 			~ServiceRef();
196 
197 			/*
198 			* This does an underlying DNSServiceRefDeallocate().  After
199 			* calling Dispose, the ServiceRef is no longer usable.
200 			*/
201 			void
202 			Dispose();
203 
204 			/*
205 			* Internal - Dispatch an EnumerateDomains callback
206 			*/
207 			void
208 			EnumerateDomainsDispatch
209 				(
210 				ServiceFlags	flags,
211 				int				interfaceIndex,
212 				ErrorCode		errorCode,
213 				String		*	replyDomain
214 				);
215 
216 			/*
217 			* Internal - Dispatch a Register callback
218 			*/
219 			void
220 			RegisterDispatch
221 				(
222 				ServiceFlags	flags,
223 				ErrorCode		errorCode,
224  				String		*	name,
225 				String		*	regtype,
226 				String		*	domain
227 				);
228 
229 			/*
230 			* Internal - Dispatch a Browse callback
231 			*/
232 			void
233 			BrowseDispatch
234 				(
235 				ServiceFlags	flags,
236 				int				interfaceIndex,
237 				ErrorCode		errorCode,
238 				String		*	serviceName,
239 				String		*	regtype,
240 				String		*	replyDomain
241 				);
242 
243 			/*
244 			* Internal - Dispatch a Resolve callback
245 			*/
246 			void
247 			ResolveDispatch
248 				(
249 				ServiceFlags	flags,
250 				int				interfaceIndex,
251 				ErrorCode		errorCode,
252 				String		*	fullname,
253 				String		*	hosttarget,
254 				int				port,
255 				Byte			txtRecord[]
256 				);
257 
258 			/*
259 			* Internal - Dispatch a RegisterRecord callback
260 			*/
261 			void
262 			RegisterRecordDispatch
263 				(
264 				ServiceFlags	flags,
265 				ErrorCode		errorCode,
266 				RecordRef	*	record
267 				);
268 
269 			/*
270 			* Internal - Dispatch a QueryRecord callback
271 			*/
272 			void
273 			QueryRecordDispatch
274 				(
275 				ServiceFlags	flags,
276 				int				interfaceIndex,
277 				ErrorCode		errorCode,
278 				String		*	fullname,
279 				int				rrtype,
280 				int				rrclass,
281 				Byte			rdata[],
282 				int				ttl
283 				);
284 
285 			/*
286 			* Internal - A non managed class to wrap a DNSServiceRef
287 			*/
288 			__nogc class ServiceRefImpl
289 			{
290 			public:
291 
292 				ServiceRefImpl
293 					(
294 					ServiceRef * outer
295 					);
296 
297 				~ServiceRefImpl();
298 
299 				/*
300 				* Sets up events for threaded operation
301 				*/
302 				void
303 				SetupEvents();
304 
305 				/*
306 				* Main processing thread
307 				*/
308 				void
309 				ProcessingThread();
310 
311 				/*
312 				* Calls DNSServiceRefDeallocate()
313 				*/
314 				void
315 				Dispose();
316 
317 				/*
318 				* Called from dnssd.dll
319 				*/
320 				static void DNSSD_API
321 				EnumerateDomainsCallback
322 					(
323 					DNSServiceRef			sdRef,
324 					DNSServiceFlags			flags,
325 					uint32_t				interfaceIndex,
326 					DNSServiceErrorType		errorCode,
327 					const char			*	replyDomain,
328 					void				*	context
329 					);
330 
331 				static void DNSSD_API
332 				RegisterCallback
333 					(
334 					DNSServiceRef			ref,
335 					DNSServiceFlags			flags,
336 					DNSServiceErrorType		errorCode,
337  					const char			*	name,
338 					const char			*	regtype,
339 					const char			*	domain,
340 					void				*	context
341 					);
342 
343 				static void DNSSD_API
344 				BrowseCallback
345 					(
346 					DNSServiceRef			sdRef,
347    					DNSServiceFlags			flags,
348 					uint32_t				interfaceIndex,
349 					DNSServiceErrorType		errorCode,
350 					const char			*	serviceName,
351 					const char			*	regtype,
352 					const char			*	replyDomain,
353 					void				*	context
354 					);
355 
356 				static void DNSSD_API
357 				ResolveCallback
358 					(
359 					DNSServiceRef			sdRef,
360 					DNSServiceFlags			flags,
361 					uint32_t				interfaceIndex,
362 					DNSServiceErrorType		errorCode,
363 					const char			*	fullname,
364 					const char			*	hosttarget,
365 					uint16_t				notAnIntPort,
366 					uint16_t				txtLen,
367 					const char			*	txtRecord,
368 					void				*	context
369 					);
370 
371 				static void DNSSD_API
372 				RegisterRecordCallback
373 					(
374 					DNSServiceRef		sdRef,
375 					DNSRecordRef		RecordRef,
376 					DNSServiceFlags		flags,
377 					DNSServiceErrorType	errorCode,
378 					void			*	context
379 					);
380 
381 				static void DNSSD_API
382 				QueryRecordCallback
383 					(
384 					DNSServiceRef			DNSServiceRef,
385 					DNSServiceFlags			flags,
386 					uint32_t				interfaceIndex,
387 					DNSServiceErrorType		errorCode,
388 					const char			*	fullname,
389 					uint16_t				rrtype,
390 					uint16_t				rrclass,
391 					uint16_t				rdlen,
392 					const void			*	rdata,
393 					uint32_t				ttl,
394 					void				*	context
395 					);
396 
397 				SOCKET				m_socket;
398 				HANDLE				m_socketEvent;
399 				HANDLE				m_stopEvent;
400 				DWORD				m_threadId;
401 				bool				m_disposed;
402 				DNSServiceRef		m_ref;
403 				gcroot<ServiceRef*> m_outer;
404 			};
405 
406 			void
407 			StartThread();
408 
409 			void
410 			ProcessingThread();
411 
412 			bool				m_bDisposed;
413 			Object			*	m_callback;
414 			Thread			*	m_thread;
415 			ServiceRefImpl	*	m_impl;
416 		};
417 
418 		/*********************************************************************************************
419 		*
420 		*   TXT Record Construction Functions
421 		*
422 		*********************************************************************************************/
423 
424 		/*
425 		* A typical calling sequence for TXT record construction is something like:
426 		*
427 		* DNSService.TextRecord tr = new DNSService.TextRecord(1024);
428 		* tr.SetValue();
429 		* tr.SetValue();
430 		* tr.SetValue();
431 		* ...
432 		* DNSServiceRegister( ... tr.GetLength(), tr.GetBytes() ... );
433 		*/
434 
435 
436 		/* TextRecord
437 		*
438 		* Opaque internal data type.
439 		* Note: Represents a DNS-SD TXT record.
440 		*/
441 
442 
443 		/* TextRecord::TextRecord()
444 		*
445 		* Creates a new empty TextRecord .
446 		*
447 		*/
448 
449 		public __gc class TextRecord
450 		{
451 		public:
452 
TextRecord()453 			TextRecord()
454 			{
455 				m_impl = new TextRecordImpl();
456 				TXTRecordCreate(&m_impl->m_ref, 0, NULL);
457 			}
458 
~TextRecord()459 			~TextRecord()
460 			{
461 				TXTRecordDeallocate(&m_impl->m_ref);
462 				delete m_impl;
463 			}
464 
465 			__nogc class TextRecordImpl
466 			{
467 			public:
468 
469 				TXTRecordRef m_ref;
470 			};
471 
472 			TextRecordImpl * m_impl;
473 
474 
475 			/* SetValue()
476 			*
477 			* Adds a key (optionally with value) to a TextRecord. If the "key" already
478 			* exists in the TextRecord, then the current value will be replaced with
479 			* the new value.
480 			* Keys may exist in four states with respect to a given TXT record:
481 			*  - Absent (key does not appear at all)
482 			*  - Present with no value ("key" appears alone)
483 			*  - Present with empty value ("key=" appears in TXT record)
484 			*  - Present with non-empty value ("key=value" appears in TXT record)
485 			* For more details refer to "Data Syntax for DNS-SD TXT Records" in
486 			* <http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt>
487 			*
488 			* key:             A null-terminated string which only contains printable ASCII
489 			*                  values (0x20-0x7E), excluding '=' (0x3D). Keys should be
490 			*                  14 characters or less (not counting the terminating null).
491 			*
492 			* value:           Any binary value. For values that represent
493 			*                  textual data, UTF-8 is STRONGLY recommended.
494 			*                  For values that represent textual data, valueSize
495 			*                  should NOT include the terminating null (if any)
496 			*                  at the end of the string.
497 			*                  If NULL, then "key" will be added with no value.
498 			*                  If non-NULL but valueSize is zero, then "key=" will be
499 			*                  added with empty value.
500 			*
501 			* exceptions:      Throws kDNSServiceErr_Invalid if the "key" string contains
502 			*                  illegal characters.
503 			*                  Throws kDNSServiceErr_NoMemory if adding this key would
504 			*                  exceed the available storage.
505 			*/
506 
507 			void
508 			SetValue
509 				(
510 				String	*	key,
511 				Byte		value[]  /* may be NULL */
512 				);
513 
514 
515 			/* RemoveValue()
516 			*
517 			* Removes a key from a TextRecord.  The "key" must be an
518 			* ASCII string which exists in the TextRecord.
519 			*
520 			* key:             A key name which exists in the TextRecord.
521 			*
522 			* exceptions:      Throws kDNSServiceErr_NoSuchKey if the "key" does not
523 			*                  exist in the TextRecord.
524 			*
525 			*/
526 
527 			void
528 			RemoveValue
529 				(
530 				String	*	key
531 				);
532 
533 
534 			/* GetLength()
535 			*
536 			* Allows you to determine the length of the raw bytes within a TextRecord.
537 			*
538 			* return value :     Returns the size of the raw bytes inside a TextRecord
539 			*                  which you can pass directly to DNSServiceRegister() or
540 			*                  to DNSServiceUpdateRecord().
541 			*                  Returns 0 if the TextRecord is empty.
542 			*
543 			*/
544 
545 			int
546 			GetLength
547 				(
548 				);
549 
550 
551 			/* GetBytes()
552 			*
553 			* Allows you to retrieve a pointer to the raw bytes within a TextRecord.
554 			*
555 			* return value:    Returns a pointer to the bytes inside the TextRecord
556 			*                  which you can pass directly to DNSServiceRegister() or
557 			*                  to DNSServiceUpdateRecord().
558 			*
559 			*/
560 
561 			Byte
562 			GetBytes
563 				(
564 				) __gc[];
565 
566 
567 			/*********************************************************************************************
568 			*
569 			*   TXT Record Parsing Functions
570 			*
571 			*********************************************************************************************/
572 
573 			/*
574 			* A typical calling sequence for TXT record parsing is something like:
575 			*
576 			* Receive TXT record data in DNSServiceResolve() callback
577 			* if (TXTRecordContainsKey(txtLen, txtRecord, "key")) then do something
578 			* val1ptr = DNSService.TextService.GetValue(txtRecord, "key1", &len1);
579 			* val2ptr = DNSService.TextService.GetValue(txtRecord, "key2", &len2);
580 			* ...
581 			* return;
582 			*
583 			*/
584 
585 			/* ContainsKey()
586 			*
587 			* Allows you to determine if a given TXT Record contains a specified key.
588 			*
589 			* txtRecord:       Pointer to the received TXT Record bytes.
590 			*
591 			* key:             A null-terminated ASCII string containing the key name.
592 			*
593 			* return value:    Returns 1 if the TXT Record contains the specified key.
594 			*                  Otherwise, it returns 0.
595 			*
596 			*/
597 
598 			static public bool
599 			ContainsKey
600 				(
601 				Byte		txtRecord[],
602 				String	*	key
603 				);
604 
605 
606 			/* GetValueBytes()
607 			*
608 			* Allows you to retrieve the value for a given key from a TXT Record.
609 			*
610 			* txtRecord:       Pointer to the received TXT Record bytes.
611 			*
612 			* key:             A null-terminated ASCII string containing the key name.
613 			*
614 			* return value:    Returns NULL if the key does not exist in this TXT record,
615 			*                  or exists with no value (to differentiate between
616 			*                  these two cases use ContainsKey()).
617 			*                  Returns byte array
618 			*                  if the key exists with empty or non-empty value.
619 			*                  For empty value, length of byte array will be zero.
620 			*                  For non-empty value, it will be the length of value data.
621 			*/
622 
623 			static public Byte
624 			GetValueBytes
625 				(
626 				Byte		txtRecord[],
627 				String	*	key
628 				) __gc[];
629 
630 
631 			/* GetCount()
632 			*
633 			* Returns the number of keys stored in the TXT Record.  The count
634 			* can be used with TXTRecordGetItemAtIndex() to iterate through the keys.
635 			*
636 			* txtRecord:       Pointer to the received TXT Record bytes.
637 			*
638 			* return value:    Returns the total number of keys in the TXT Record.
639 			*
640 			*/
641 
642 			static public int
643 			GetCount
644 				(
645 				Byte	txtRecord[]
646 				);
647 
648 
649 			/* GetItemAtIndex()
650 			*
651 			* Allows you to retrieve a key name and value pointer, given an index into
652 			* a TXT Record.  Legal index values range from zero to TXTRecordGetCount()-1.
653 			* It's also possible to iterate through keys in a TXT record by simply
654 			* calling TXTRecordGetItemAtIndex() repeatedly, beginning with index zero
655 			* and increasing until TXTRecordGetItemAtIndex() returns kDNSServiceErr_Invalid.
656 			*
657 			* On return:
658 			* For keys with no value, *value is set to NULL and *valueLen is zero.
659 			* For keys with empty value, *value is non-NULL and *valueLen is zero.
660 			* For keys with non-empty value, *value is non-NULL and *valueLen is non-zero.
661 			*
662 			* txtRecord:       Pointer to the received TXT Record bytes.
663 			*
664 			* index:           An index into the TXT Record.
665 			*
666 			* key:             A string buffer used to store the key name.
667 			*                  On return, the buffer contains a string
668 			*                  giving the key name. DNS-SD TXT keys are usually
669 			*                  14 characters or less.
670 			*
671 			* return value:    Record bytes that holds the value data.
672 			*
673 			* exceptions:      Throws kDNSServiceErr_Invalid if index is greater than
674 			*                  GetCount()-1.
675 			*/
676 
677 			static public Byte
678 			GetItemAtIndex
679 				(
680 				Byte				txtRecord[],
681 				int					index,
682 				[Out] String	**	key
683 				) __gc[];
684 		};
685 
686 
687 		public __abstract __gc class DNSService
688 		{
689 		public:
690 
691 			/*********************************************************************************************
692 			*
693 			* Domain Enumeration
694 			*
695 			*********************************************************************************************/
696 
697 			/* DNSServiceEnumerateDomains()
698 			*
699 			* Asynchronously enumerate domains available for browsing and registration.
700 			* Currently, the only domain returned is "local.", but other domains will be returned in future.
701 			*
702 			* The enumeration MUST be cancelled via DNSServiceRefDeallocate() when no more domains
703 			* are to be found.
704 			*
705 			*
706 			* EnumerateDomainsReply Delegate
707 			*
708 			* This Delegate is invoked upon a reply from an EnumerateDomains call.
709 			*
710 			* sdRef:           The DNSServiceRef initialized by DNSServiceEnumerateDomains().
711 			*
712 			* flags:           Possible values are:
713 			*                  MoreComing
714 			*                  Add
715 			*                  Default
716 			*
717 			* interfaceIndex:  Specifies the interface on which the domain exists.  (The index for a given
718 			*                  interface is determined via the if_nametoindex() family of calls.)
719 			*
720 			* errorCode:       Will be NoError (0) on success, otherwise indicates
721 			*                  the failure that occurred (other parameters are undefined if errorCode is nonzero).
722 			*
723 			* replyDomain:     The name of the domain.
724 			*
725 			*/
726 
727 			__delegate void
728 			EnumerateDomainsReply
729 				(
730 				ServiceRef	*	sdRef,
731 				ServiceFlags	flags,
732 				int				interfaceIndex,
733 				ErrorCode		errorCode,
734 				String		*	replyDomain
735 				);
736 
737 			/* DNSServiceEnumerateDomains() Parameters:
738 			*
739 			*
740 			* flags:           Possible values are:
741 			*                  BrowseDomains to enumerate domains recommended for browsing.
742 			*                  RegistrationDomains to enumerate domains recommended
743 			*                  for registration.
744 			*
745 			* interfaceIndex:  If non-zero, specifies the interface on which to look for domains.
746 			*                  (the index for a given interface is determined via the if_nametoindex()
747 			*                  family of calls.)  Most applications will pass 0 to enumerate domains on
748 			*                  all interfaces.
749 			*
750 			* callback:        The delegate to be called when a domain is found or the call asynchronously
751 			*                  fails.
752 			*
753 			*
754 			* return value:    Returns initialize ServiceRef on succeses (any subsequent, asynchronous
755 			*                  errors are delivered to the delegate), otherwise throws an exception indicating
756 			*                  the error that occurred (the callback is not invoked and the ServiceRef
757 			*                  is not initialized.)
758 			*/
759 
760 			static public ServiceRef*
761 			EnumerateDomains
762 				(
763 				int							flags,
764 				int							interfaceIndex,
765 				EnumerateDomainsReply	*	callback
766 				);
767 
768 			/*********************************************************************************************
769 			*
770 			*  Service Registration
771 			*
772 			*********************************************************************************************/
773 
774 			/* Register a service that is discovered via Browse() and Resolve() calls.
775 			*
776 			* RegisterReply() Callback Parameters:
777 			*
778 			* sdRef:           The ServiceRef initialized by Register().
779 			*
780 			* flags:           Currently unused, reserved for future use.
781 			*
782 			* errorCode:       Will be NoError on success, otherwise will
783 			*                  indicate the failure that occurred (including name conflicts, if the
784 			*                  NoAutoRename flag was passed to the
785 			*                  callout.)  Other parameters are undefined if errorCode is nonzero.
786 			*
787 			* name:            The service name registered (if the application did not specify a name in
788 			*                  DNSServiceRegister(), this indicates what name was automatically chosen).
789 			*
790 			* regtype:         The type of service registered, as it was passed to the callout.
791 			*
792 			* domain:          The domain on which the service was registered (if the application did not
793 			*                  specify a domain in Register(), this indicates the default domain
794 			*                  on which the service was registered).
795 			*
796 			*/
797 
798 			__delegate void
799 			RegisterReply
800 				(
801 				ServiceRef	*	sdRef,
802 				ServiceFlags	flags,
803 				ErrorCode		errorCode,
804 				String		*	name,
805 				String		*	regtype,
806 				String		*	domain
807 				);
808 
809 			/* Register()  Parameters:
810 			*
811 			* flags:           Indicates the renaming behavior on name conflict (most applications
812 			*                  will pass 0).  See flag definitions above for details.
813 			*
814 			* interfaceIndex:  If non-zero, specifies the interface on which to register the service
815 			*                  (the index for a given interface is determined via the if_nametoindex()
816 			*                  family of calls.)  Most applications will pass 0 to register on all
817 			*                  available interfaces.  Pass -1 to register a service only on the local
818 			*                  machine (service will not be visible to remote hosts.)
819 			*
820 			* name:            If non-NULL, specifies the service name to be registered.
821 			*                  Most applications will not specify a name, in which case the
822 			*                  computer name is used (this name is communicated to the client via
823 			*                  the callback).
824 			*
825 			* regtype:         The service type followed by the protocol, separated by a dot
826 			*                  (e.g. "_ftp._tcp").  The transport protocol must be "_tcp" or "_udp".
827 			*                  New service types should be registered at htp://www.dns-sd.org/ServiceTypes.html.
828 			*
829 			* domain:          If non-NULL, specifies the domain on which to advertise the service.
830 			*                  Most applications will not specify a domain, instead automatically
831 			*                  registering in the default domain(s).
832 			*
833 			* host:            If non-NULL, specifies the SRV target host name.  Most applications
834 			*                  will not specify a host, instead automatically using the machine's
835 			*                  default host name(s).  Note that specifying a non-NULL host does NOT
836 			*                  create an address record for that host - the application is responsible
837 			*                  for ensuring that the appropriate address record exists, or creating it
838 			*                  via DNSServiceRegisterRecord().
839 			*
840 			* port:            The port, in host byte order, on which the service accepts connections.
841 			*                  Pass 0 for a "placeholder" service (i.e. a service that will not be discovered
842 			*                  by browsing, but will cause a name conflict if another client tries to
843 			*                  register that same name).  Most clients will not use placeholder services.
844 			*
845 			* txtRecord:       The txt record rdata.  May be NULL.  Note that a non-NULL txtRecord
846 			*                  MUST be a properly formatted DNS TXT record, i.e. <length byte> <data>
847 			*                  <length byte> <data> ...
848 			*
849 			* callback:        The delegate to be called when the registration completes or asynchronously
850 			*                  fails.  The client MAY pass NULL for the callback -  The client will NOT be notified
851 			*                  of the default values picked on its behalf, and the client will NOT be notified of any
852 			*                  asynchronous errors (e.g. out of memory errors, etc.) that may prevent the registration
853 			*                  of the service.  The client may NOT pass the NoAutoRename flag if the callback is NULL.
854 			*                  The client may still deregister the service at any time via DNSServiceRefDeallocate().
855 			*
856 			* return value:    Returns initialize ServiceRef (any subsequent, asynchronous
857 			*                  errors are delivered to the callback), otherwise throws an exception indicating
858 			*                  the error that occurred (the callback is never invoked and the DNSServiceRef
859 			*                  is not initialized.)
860 			*
861 			*/
862 			static public ServiceRef*
863 			Register
864 				(
865 				int					flags,
866 				int					interfaceIndex,
867 				String			*	name,
868 				String			*	regtype,
869 				String			*	domain,
870 				String			*	host,
871 				int					port,
872 				Byte				txtRecord[],
873 				RegisterReply	*	callback
874 				);
875 
876 			/* AddRecord()
877 			*
878 			* Add a record to a registered service.  The name of the record will be the same as the
879 			* registered service's name.
880 			* The record can later be updated or deregistered by passing the RecordRef initialized
881 			* by this function to UpdateRecord() or RemoveRecord().
882 			*
883 			*
884 			* Parameters;
885 			*
886 			* sdRef:           A ServiceRef initialized by Register().
887 			*
888 			* RecordRef:       A pointer to an uninitialized RecordRef.  Upon succesfull completion of this
889 			*                  call, this ref may be passed to UpdateRecord() or RemoveRecord().
890 			*                  If the above ServiceRef is disposed, RecordRef is also
891 			*                  invalidated and may not be used further.
892 			*
893 			* flags:           Currently ignored, reserved for future use.
894 			*
895 			* rrtype:          The type of the record (e.g. TXT, SRV, etc), as defined in nameser.h.
896 			*
897 			* rdata:           The raw rdata to be contained in the added resource record.
898 			*
899 			* ttl:             The time to live of the resource record, in seconds.
900 			*
901 			* return value:    Returns initialized RecordRef, otherwise throws
902 			*                  an exception indicating the error that occurred (the RecordRef is not initialized).
903 			*/
904 
905 			static public RecordRef*
906 			AddRecord
907 				(
908 				ServiceRef	*	sref,
909 				int				flags,
910 				int				rrtype,
911 				Byte			rdata[],
912 				int				ttl
913 				);
914 
915 			/* UpdateRecord
916 			*
917 			* Update a registered resource record.  The record must either be:
918 			*   - The primary txt record of a service registered via Register()
919 			*   - A record added to a registered service via AddRecord()
920 			*   - An individual record registered by RegisterRecord()
921 			*
922 			*
923 			* Parameters:
924 			*
925 			* sdRef:           A ServiceRef that was initialized by Register()
926 			*                  or CreateConnection().
927 			*
928 			* RecordRef:       A RecordRef initialized by AddRecord, or NULL to update the
929 			*                  service's primary txt record.
930 			*
931 			* flags:           Currently ignored, reserved for future use.
932 			*
933 			* rdata:           The new rdata to be contained in the updated resource record.
934 			*
935 			* ttl:             The time to live of the updated resource record, in seconds.
936 			*
937 			* return value:    No return value on success, otherwise throws an exception
938 			*                  indicating the error that occurred.
939 			*/
940 			static public void
941 			UpdateRecord
942 				(
943 				ServiceRef	*	sref,
944 				RecordRef	*	record,
945 				int				flags,
946 				Byte			rdata[],
947 				int				ttl
948 				);
949 
950 			/* RemoveRecord
951 			*
952 			* Remove a record previously added to a service record set via AddRecord(), or deregister
953 			* an record registered individually via RegisterRecord().
954 			*
955 			* Parameters:
956 			*
957 			* sdRef:           A ServiceRef initialized by Register() (if the
958 			*                  record being removed was registered via AddRecord()) or by
959 			*                  CreateConnection() (if the record being removed was registered via
960 			*                  RegisterRecord()).
961 			*
962 			* recordRef:       A RecordRef initialized by a successful call to AddRecord()
963 			*                  or RegisterRecord().
964 			*
965 			* flags:           Currently ignored, reserved for future use.
966 			*
967 			* return value:    Nothing on success, otherwise throws an
968 			*                  exception indicating the error that occurred.
969 			*/
970 
971 			static public void
972 			RemoveRecord
973 							(
974 							ServiceRef	*	sref,
975 							RecordRef	*	record,
976 							int				flags
977 							);
978 
979 			/*********************************************************************************************
980 			*
981 			*  Service Discovery
982 			*
983 			*********************************************************************************************/
984 
985 			/* Browse for instances of a service.
986 			*
987 			*
988 			* BrowseReply() Parameters:
989 			*
990 			* sdRef:           The DNSServiceRef initialized by Browse().
991 			*
992 			* flags:           Possible values are MoreComing and Add.
993 			*                  See flag definitions for details.
994 			*
995 			* interfaceIndex:  The interface on which the service is advertised.  This index should
996 			*                  be passed to Resolve() when resolving the service.
997 			*
998 			* errorCode:       Will be NoError (0) on success, otherwise will
999 			*                  indicate the failure that occurred.  Other parameters are undefined if
1000 			*                  the errorCode is nonzero.
1001 			*
1002 			* serviceName:     The service name discovered.
1003 			*
1004 			* regtype:         The service type, as passed in to Browse().
1005 			*
1006 			* domain:          The domain on which the service was discovered (if the application did not
1007 			*                  specify a domain in Browse(), this indicates the domain on which the
1008 			*                  service was discovered.)
1009 			*
1010 			*/
1011 
1012 			__delegate void
1013 			BrowseReply
1014 				(
1015 				ServiceRef	*	sdRef,
1016 				ServiceFlags	flags,
1017 				int				interfaceIndex,
1018 				ErrorCode		errorCode,
1019 				String		*	name,
1020 				String		*	type,
1021 				String		*	domain
1022 				);
1023 
1024 			/* DNSServiceBrowse() Parameters:
1025 			*
1026 			* sdRef:           A pointer to an uninitialized ServiceRef.  Call ServiceRef.Dispose()
1027 			*                  to terminate the browse.
1028 			*
1029 			* flags:           Currently ignored, reserved for future use.
1030 			*
1031 			* interfaceIndex:  If non-zero, specifies the interface on which to browse for services
1032 			*                  (the index for a given interface is determined via the if_nametoindex()
1033 			*                  family of calls.)  Most applications will pass 0 to browse on all available
1034 			*                  interfaces.  Pass -1 to only browse for services provided on the local host.
1035 			*
1036 			* regtype:         The service type being browsed for followed by the protocol, separated by a
1037 			*                  dot (e.g. "_ftp._tcp").  The transport protocol must be "_tcp" or "_udp".
1038 			*
1039 			* domain:          If non-NULL, specifies the domain on which to browse for services.
1040 			*                  Most applications will not specify a domain, instead browsing on the
1041 			*                  default domain(s).
1042 			*
1043 			* callback:        The delegate to be called when an instance of the service being browsed for
1044 			*                  is found, or if the call asynchronously fails.
1045 			*
1046 			* return value:    Returns initialized ServiceRef on succeses (any subsequent, asynchronous
1047 			*                  errors are delivered to the callback), otherwise throws an exception indicating
1048 			*                  the error that occurred (the callback is not invoked and the ServiceRef
1049 			*                  is not initialized.)
1050 			*/
1051 
1052 			static public ServiceRef*
1053 			Browse
1054 				(
1055 				int				flags,
1056 				int				interfaceIndex,
1057 				String		*	regtype,
1058 				String		*	domain,
1059 				BrowseReply	*	callback
1060 				);
1061 
1062 			/* ResolveReply() Parameters:
1063 			*
1064 			* Resolve a service name discovered via Browse() to a target host name, port number, and
1065 			* txt record.
1066 			*
1067 			* Note: Applications should NOT use Resolve() solely for txt record monitoring - use
1068 			* QueryRecord() instead, as it is more efficient for this task.
1069 			*
1070 			* Note: When the desired results have been returned, the client MUST terminate the resolve by calling
1071 			* ServiceRef.Dispose().
1072 			*
1073 			* Note: Resolve() behaves correctly for typical services that have a single SRV record and
1074 			* a single TXT record (the TXT record may be empty.)  To resolve non-standard services with multiple
1075 			* SRV or TXT records, QueryRecord() should be used.
1076 			*
1077 			* ResolveReply Callback Parameters:
1078 			*
1079 			* sdRef:           The DNSServiceRef initialized by Resolve().
1080 			*
1081 			* flags:           Currently unused, reserved for future use.
1082 			*
1083 			* interfaceIndex:  The interface on which the service was resolved.
1084 			*
1085 			* errorCode:       Will be NoError (0) on success, otherwise will
1086 			*                  indicate the failure that occurred.  Other parameters are undefined if
1087 			*                  the errorCode is nonzero.
1088 			*
1089 			* fullname:        The full service domain name, in the form <servicename>.<protocol>.<domain>.
1090 			*                  (Any literal dots (".") are escaped with a backslash ("\."), and literal
1091 			*                  backslashes are escaped with a second backslash ("\\"), e.g. a web server
1092 			*                  named "Dr. Pepper" would have the fullname  "Dr\.\032Pepper._http._tcp.local.").
1093 			*                  This is the appropriate format to pass to standard system DNS APIs such as
1094 			*                  res_query(), or to the special-purpose functions included in this API that
1095 			*                  take fullname parameters.
1096 			*
1097 			* hosttarget:      The target hostname of the machine providing the service.  This name can
1098 			*                  be passed to functions like gethostbyname() to identify the host's IP address.
1099 			*
1100 			* port:            The port, in host byte order, on which connections are accepted for this service.
1101 			*
1102 			* txtRecord:       The service's primary txt record, in standard txt record format.
1103 			*
1104 			*/
1105 
1106 			__delegate void
1107 			ResolveReply
1108 				(
1109 				ServiceRef	*	sdRef,
1110 				ServiceFlags	flags,
1111 				int				interfaceIndex,
1112 				ErrorCode		errorCode,
1113 				String		*	fullName,
1114 				String		*	hostName,
1115 				int				port,
1116 				Byte			txtRecord[]
1117 				);
1118 
1119 			/* Resolve() Parameters
1120 			*
1121 			* flags:           Currently ignored, reserved for future use.
1122 			*
1123 			* interfaceIndex:  The interface on which to resolve the service.  The client should
1124 			*                  pass the interface on which the servicename was discovered, i.e.
1125 			*                  the interfaceIndex passed to the DNSServiceBrowseReply callback,
1126 			*                  or 0 to resolve the named service on all available interfaces.
1127 			*
1128 			* name:            The servicename to be resolved.
1129 			*
1130 			* regtype:         The service type being resolved followed by the protocol, separated by a
1131 			*                  dot (e.g. "_ftp._tcp").  The transport protocol must be "_tcp" or "_udp".
1132 			*
1133 			* domain:          The domain on which the service is registered, i.e. the domain passed
1134 			*                  to the DNSServiceBrowseReply callback.
1135 			*
1136 			* callback:        The delegate to be called when a result is found, or if the call
1137 			*                  asynchronously fails.
1138 			*
1139 			*
1140 			* return value:    Returns initialized ServiceRef on succeses (any subsequent, asynchronous
1141 			*                  errors are delivered to the callback), otherwise throws an exception indicating
1142 			*                  the error that occurred (the callback is never invoked and the DNSServiceRef
1143 			*                  is not initialized.)
1144 			*/
1145 
1146 			static public ServiceRef*
1147 			Resolve
1148 				(
1149 				int					flags,
1150 				int					interfaceIndex,
1151 				String			*	name,
1152 				String			*	regtype,
1153 				String			*	domain,
1154 				ResolveReply	*	callback
1155 				);
1156 
1157 			/*********************************************************************************************
1158 			*
1159 			*  Special Purpose Calls (most applications will not use these)
1160 			*
1161 			*********************************************************************************************/
1162 
1163 			/* CreateConnection/RegisterRecord
1164 			*
1165 			* Register an individual resource record on a connected ServiceRef.
1166 			*
1167 			* Note that name conflicts occurring for records registered via this call must be handled
1168 			* by the client in the callback.
1169 			*
1170 			*
1171 			* RecordReply() parameters:
1172 			*
1173 			* sdRef:           The connected ServiceRef initialized by
1174 			*                  CreateConnection().
1175 			*
1176 			* RecordRef:       The RecordRef initialized by RegisterRecord().  If the above
1177 			*                  ServiceRef.Dispose is called, this RecordRef is
1178 			*                  invalidated, and may not be used further.
1179 			*
1180 			* flags:           Currently unused, reserved for future use.
1181 			*
1182 			* errorCode:       Will be NoError on success, otherwise will
1183 			*                  indicate the failure that occurred (including name conflicts.)
1184 			*                  Other parameters are undefined if errorCode is nonzero.
1185 			*
1186 			*/
1187 
1188 			__delegate void
1189 			RegisterRecordReply
1190 				(
1191 				ServiceRef	*	sdRef,
1192 				ServiceFlags	flags,
1193 				ErrorCode		errorCode,
1194 				RecordRef	*	record
1195 				);
1196 
1197 			/* CreateConnection()
1198 			*
1199 			* Create a connection to the daemon allowing efficient registration of
1200 			* multiple individual records.
1201 			*
1202 			*
1203 			* Parameters:
1204 			*
1205 			* callback:        The delegate to be called when a result is found, or if the call
1206 			*                  asynchronously fails (e.g. because of a name conflict.)
1207 			*
1208 			* return value:    Returns initialize ServiceRef on success, otherwise throws
1209 			*                  an exception indicating the specific failure that occurred (in which
1210 			*                  case the ServiceRef is not initialized).
1211 			*/
1212 
1213 			static public ServiceRef*
1214 			CreateConnection
1215 				(
1216 				RegisterRecordReply * callback
1217 				);
1218 
1219 
1220 			/* RegisterRecord() Parameters:
1221 			*
1222 			* sdRef:           A ServiceRef initialized by CreateConnection().
1223 			*
1224 			* RecordRef:       A pointer to an uninitialized RecordRef.  Upon succesfull completion of this
1225 			*                  call, this ref may be passed to UpdateRecord() or RemoveRecord().
1226 			*                  (To deregister ALL records registered on a single connected ServiceRef
1227 			*                  and deallocate each of their corresponding RecordRefs, call
1228 			*                  ServiceRef.Dispose()).
1229 			*
1230 			* flags:           Possible values are Shared or Unique
1231 			*                  (see flag type definitions for details).
1232 			*
1233 			* interfaceIndex:  If non-zero, specifies the interface on which to register the record
1234 			*                  (the index for a given interface is determined via the if_nametoindex()
1235 			*                  family of calls.)  Passing 0 causes the record to be registered on all interfaces.
1236 			*                  Passing -1 causes the record to only be visible on the local host.
1237 			*
1238 			* fullname:        The full domain name of the resource record.
1239 			*
1240 			* rrtype:          The numerical type of the resource record (e.g. PTR, SRV, etc), as defined
1241 			*                  in nameser.h.
1242 			*
1243 			* rrclass:         The class of the resource record, as defined in nameser.h (usually 1 for the
1244 			*                  Internet class).
1245 			*
1246 			* rdata:           A pointer to the raw rdata, as it is to appear in the DNS record.
1247 			*
1248 			* ttl:             The time to live of the resource record, in seconds.
1249 			*
1250 			*
1251 			* return value:    Returns initialize RecordRef on succeses (any subsequent, asynchronous
1252 			*                  errors are delivered to the callback), otherwise throws an exception indicating
1253 			*                  the error that occurred (the callback is never invoked and the RecordRef is
1254 			*                  not initialized.)
1255 			*/
1256 			static public RecordRef*
1257 			RegisterRecord
1258 				(
1259 				ServiceRef			*	sdRef,
1260 				ServiceFlags			flags,
1261 				int						interfaceIndex,
1262 				String				*	fullname,
1263 				int						rrtype,
1264 				int						rrclass,
1265 				Byte					rdata[],
1266 				int						ttl
1267 				);
1268 
1269 
1270 			/* DNSServiceQueryRecord
1271 			*
1272 			* Query for an arbitrary DNS record.
1273 			*
1274 			*
1275 			* QueryRecordReply() Delegate Parameters:
1276 			*
1277 			* sdRef:           The ServiceRef initialized by QueryRecord().
1278 			*
1279 			* flags:           Possible values are MoreComing and
1280 			*                  Add.  The Add flag is NOT set for PTR records
1281 			*                  with a ttl of 0, i.e. "Remove" events.
1282 			*
1283 			* interfaceIndex:  The interface on which the query was resolved (the index for a given
1284 			*                  interface is determined via the if_nametoindex() family of calls).
1285 			*
1286 			* errorCode:       Will be kDNSServiceErr_NoError on success, otherwise will
1287 			*                  indicate the failure that occurred.  Other parameters are undefined if
1288 			*                  errorCode is nonzero.
1289 			*
1290 			* fullname:        The resource record's full domain name.
1291 			*
1292 			* rrtype:          The resource record's type (e.g. PTR, SRV, etc) as defined in nameser.h.
1293 			*
1294 			* rrclass:         The class of the resource record, as defined in nameser.h (usually 1).
1295 			*
1296 			* rdata:           The raw rdata of the resource record.
1297 			*
1298 			* ttl:             The resource record's time to live, in seconds.
1299 			*
1300 			*/
1301 
1302 			__delegate void
1303 			QueryRecordReply
1304 				(
1305 				ServiceRef	*	sdRef,
1306 				ServiceFlags	flags,
1307 				int				interfaceIndex,
1308 				ErrorCode		errorCode,
1309 				String		*	fullName,
1310 				int				rrtype,
1311 				int				rrclass,
1312 				Byte			rdata[],
1313 				int				ttl
1314 				);
1315 
1316 			/* QueryRecord() Parameters:
1317 			*
1318 			* flags:           Pass LongLivedQuery to create a "long-lived" unicast
1319 			*                  query in a non-local domain.  Without setting this flag, unicast queries
1320 			*                  will be one-shot - that is, only answers available at the time of the call
1321 			*                  will be returned.  By setting this flag, answers (including Add and Remove
1322 			*                  events) that become available after the initial call is made will generate
1323 			*                  callbacks.  This flag has no effect on link-local multicast queries.
1324 			*
1325 			* interfaceIndex:  If non-zero, specifies the interface on which to issue the query
1326 			*                  (the index for a given interface is determined via the if_nametoindex()
1327 			*                  family of calls.)  Passing 0 causes the name to be queried for on all
1328 			*                  interfaces.  Passing -1 causes the name to be queried for only on the
1329 			*                  local host.
1330 			*
1331 			* fullname:        The full domain name of the resource record to be queried for.
1332 			*
1333 			* rrtype:          The numerical type of the resource record to be queried for (e.g. PTR, SRV, etc)
1334 			*                  as defined in nameser.h.
1335 			*
1336 			* rrclass:         The class of the resource record, as defined in nameser.h
1337 			*                  (usually 1 for the Internet class).
1338 			*
1339 			* callback:        The delegate to be called when a result is found, or if the call
1340 			*                  asynchronously fails.
1341 			*
1342 			*
1343 			* return value:    Returns initialized ServiceRef on succeses (any subsequent, asynchronous
1344 			*                  errors are delivered to the callback), otherwise throws an exception indicating
1345 			*                  the error that occurred (the callback is never invoked and the ServiceRef
1346 			*                  is not initialized.)
1347 			*/
1348 
1349 			static public ServiceRef*
1350 			QueryRecord
1351 				(
1352 				ServiceFlags			flags,
1353 				int						interfaceIndex,
1354 				String				*	fullname,
1355 				int						rrtype,
1356 				int						rrclass,
1357 				QueryRecordReply	*	callback
1358 				);
1359 
1360 			/* ReconfirmRecord
1361 			*
1362 			* Instruct the daemon to verify the validity of a resource record that appears to
1363 			* be out of date (e.g. because tcp connection to a service's target failed.)
1364 			* Causes the record to be flushed from the daemon's cache (as well as all other
1365 			* daemons' caches on the network) if the record is determined to be invalid.
1366 			*
1367 			* Parameters:
1368 			*
1369 			* flags:           Currently unused, reserved for future use.
1370 			*
1371 			* fullname:        The resource record's full domain name.
1372 			*
1373 			* rrtype:          The resource record's type (e.g. PTR, SRV, etc) as defined in nameser.h.
1374 			*
1375 			* rrclass:         The class of the resource record, as defined in nameser.h (usually 1).
1376 			*
1377 			* rdata:           The raw rdata of the resource record.
1378 			*
1379 			*/
1380 			static public void
1381 			ReconfirmRecord
1382 				(
1383 				ServiceFlags	flags,
1384 				int				interfaceIndex,
1385 				String		*	fullname,
1386 				int				rrtype,
1387 				int				rrclass,
1388 				Byte			rdata[]
1389 				);
1390 		};
1391 	}
1392 }
1393