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
42using namespace System;
43using namespace System::Net;
44using namespace System::Runtime::InteropServices;
45using namespace System::Threading;
46using namespace System::Collections;
47
48
49namespace 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
162			RecordRef()
163			{
164				m_impl = new RecordRefImpl;
165				m_impl->m_ref = NULL;
166			}
167
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
453			TextRecord()
454			{
455				m_impl = new TextRecordImpl();
456				TXTRecordCreate(&m_impl->m_ref, 0, NULL);
457			}
458
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