• 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 // This is the main DLL file.
19 
20 #include "stdafx.h"
21 
22 #include "dnssd_NET.h"
23 #include "DebugServices.h"
24 #include "PString.h"
25 
26 
27 using namespace System::Net::Sockets;
28 using namespace System::Diagnostics;
29 using namespace Apple;
30 using namespace Apple::DNSSD;
31 
32 
33 //===========================================================================================================================
34 //	Constants
35 //===========================================================================================================================
36 
37 #define	DEBUG_NAME	"[dnssd.NET] "
38 
39 //
40 // ConvertToString
41 //
42 static String*
ConvertToString(const char * utf8String)43 ConvertToString(const char * utf8String)
44 {
45 	return __gc new String(utf8String, 0, strlen(utf8String), __gc new UTF8Encoding(true, true));
46 }
47 
48 
49 //
50 // class ServiceRef
51 //
52 // ServiceRef serves as the base class for all DNSService operations.
53 //
54 // It manages the DNSServiceRef, and implements processing the
55 // result
56 //
ServiceRef(Object * callback)57 ServiceRef::ServiceRef(Object * callback)
58 :
59 	m_bDisposed(false),
60 	m_callback(callback),
61 	m_thread(NULL)
62 {
63 	m_impl = new ServiceRefImpl(this);
64 }
65 
66 
~ServiceRef()67 ServiceRef::~ServiceRef()
68 {
69 }
70 
71 
72 //
73 // StartThread
74 //
75 // Starts the main processing thread
76 //
77 void
StartThread()78 ServiceRef::StartThread()
79 {
80 	check( m_impl != NULL );
81 
82 	m_impl->SetupEvents();
83 
84 	m_thread		=	new Thread(new ThreadStart(this, &Apple::DNSSD::ServiceRef::ProcessingThread));
85 	m_thread->Name	=	S"DNSService Thread";
86 	m_thread->IsBackground = true;
87 
88 	m_thread->Start();
89 }
90 
91 
92 //
93 // ProcessingThread
94 //
95 // The Thread class can only invoke methods in MC++ types.  So we
96 // make a ProcessingThread method that forwards to the impl
97 //
98 void
ProcessingThread()99 ServiceRef::ProcessingThread()
100 {
101 	m_impl->ProcessingThread();
102 }
103 
104 
105 //
106 // Dispose
107 //
108 // Calls impl-Dispose().  This ultimately will call DNSServiceRefDeallocate()
109 //
110 void
Dispose()111 ServiceRef::Dispose()
112 {
113 	check(m_impl != NULL);
114 	check(m_bDisposed == false);
115 
116 	if (!m_bDisposed)
117 	{
118 		m_bDisposed = true;
119 
120 		//
121 		// Call Dispose.  This won't call DNSServiceRefDeallocate()
122 		// necessarily. It depends on what thread this is being
123 		// called in.
124 		//
125 		m_impl->Dispose();
126 		m_impl = NULL;
127 
128 		m_thread = NULL;
129 
130 		GC::SuppressFinalize(this);
131 	}
132 }
133 
134 
135 //
136 // EnumerateDomainsDispatch
137 //
138 // Dispatch a reply to the delegate.
139 //
140 void
EnumerateDomainsDispatch(ServiceFlags flags,int interfaceIndex,ErrorCode errorCode,String * replyDomain)141 ServiceRef::EnumerateDomainsDispatch
142 						(
143 						ServiceFlags	flags,
144 						int				interfaceIndex,
145 						ErrorCode		errorCode,
146 						String		*	replyDomain
147 						)
148 {
149 	if ((m_callback != NULL) && (m_impl != NULL))
150 	{
151 		DNSService::EnumerateDomainsReply * OnEnumerateDomainsReply = static_cast<DNSService::EnumerateDomainsReply*>(m_callback);
152 		OnEnumerateDomainsReply(this, flags, interfaceIndex, errorCode, replyDomain);
153 	}
154 }
155 
156 
157 //
158 // RegisterDispatch
159 //
160 // Dispatch a reply to the delegate.
161 //
162 void
RegisterDispatch(ServiceFlags flags,ErrorCode errorCode,String * name,String * regtype,String * domain)163 ServiceRef::RegisterDispatch
164 				(
165 				ServiceFlags	flags,
166 				ErrorCode		errorCode,
167  				String		*	name,
168 				String		*	regtype,
169 				String		*	domain
170 				)
171 {
172 	if ((m_callback != NULL) && (m_impl != NULL))
173 	{
174 		DNSService::RegisterReply * OnRegisterReply = static_cast<DNSService::RegisterReply*>(m_callback);
175 		OnRegisterReply(this, flags, errorCode, name, regtype, domain);
176 	}
177 }
178 
179 
180 //
181 // BrowseDispatch
182 //
183 // Dispatch a reply to the delegate.
184 //
185 void
BrowseDispatch(ServiceFlags flags,int interfaceIndex,ErrorCode errorCode,String * serviceName,String * regtype,String * replyDomain)186 ServiceRef::BrowseDispatch
187 			(
188 			ServiceFlags	flags,
189 			int				interfaceIndex,
190 			ErrorCode		errorCode,
191 			String		*	serviceName,
192 			String		*	regtype,
193 			String		*	replyDomain
194 			)
195 {
196 	if ((m_callback != NULL) && (m_impl != NULL))
197 	{
198 		DNSService::BrowseReply * OnBrowseReply = static_cast<DNSService::BrowseReply*>(m_callback);
199 		OnBrowseReply(this, flags, interfaceIndex, errorCode, serviceName, regtype, replyDomain);
200 	}
201 }
202 
203 
204 //
205 // ResolveDispatch
206 //
207 // Dispatch a reply to the delegate.
208 //
209 void
ResolveDispatch(ServiceFlags flags,int interfaceIndex,ErrorCode errorCode,String * fullname,String * hosttarget,int port,Byte txtRecord[])210 ServiceRef::ResolveDispatch
211 			(
212 			ServiceFlags	flags,
213 			int				interfaceIndex,
214 			ErrorCode		errorCode,
215 			String		*	fullname,
216 			String		*	hosttarget,
217 			int				port,
218 			Byte			txtRecord[]
219 			)
220 {
221 	if ((m_callback != NULL) && (m_impl != NULL))
222 	{
223 		DNSService::ResolveReply * OnResolveReply = static_cast<DNSService::ResolveReply*>(m_callback);
224 		OnResolveReply(this, flags, interfaceIndex, errorCode, fullname, hosttarget, port, txtRecord);
225 	}
226 }
227 
228 
229 //
230 // RegisterRecordDispatch
231 //
232 // Dispatch a reply to the delegate.
233 //
234 void
RegisterRecordDispatch(ServiceFlags flags,ErrorCode errorCode,RecordRef * record)235 ServiceRef::RegisterRecordDispatch
236 				(
237 				ServiceFlags	flags,
238 				ErrorCode		errorCode,
239 				RecordRef	*	record
240 				)
241 {
242 	if ((m_callback != NULL) && (m_impl != NULL))
243 	{
244 		DNSService::RegisterRecordReply * OnRegisterRecordReply = static_cast<DNSService::RegisterRecordReply*>(m_callback);
245 		OnRegisterRecordReply(this, flags, errorCode, record);
246 	}
247 }
248 
249 
250 //
251 // QueryRecordDispatch
252 //
253 // Dispatch a reply to the delegate.
254 //
255 void
QueryRecordDispatch(ServiceFlags flags,int interfaceIndex,ErrorCode errorCode,String * fullname,int rrtype,int rrclass,Byte rdata[],int ttl)256 ServiceRef::QueryRecordDispatch
257 					(
258 					ServiceFlags	flags,
259 					int				interfaceIndex,
260 					ErrorCode		errorCode,
261 					String		*	fullname,
262 					int				rrtype,
263 					int				rrclass,
264 					Byte			rdata[],
265 					int				ttl
266 					)
267 {
268 	if ((m_callback != NULL) && (m_impl != NULL))
269 	{
270 		DNSService::QueryRecordReply * OnQueryRecordReply = static_cast<DNSService::QueryRecordReply*>(m_callback);
271 		OnQueryRecordReply(this, flags, interfaceIndex, errorCode, fullname, rrtype, rrclass, rdata, ttl);
272 	}
273 }
274 
275 
276 //
277 // ServiceRefImpl::ServiceRefImpl()
278 //
279 // Constructs a new ServiceRefImpl.  We save the pointer to our enclosing
280 // class in a gcroot handle.  This satisfies the garbage collector as
281 // the outer class is a managed type
282 //
ServiceRefImpl(ServiceRef * outer)283 ServiceRef::ServiceRefImpl::ServiceRefImpl(ServiceRef * outer)
284 :
285 	m_socketEvent(NULL),
286 	m_stopEvent(NULL),
287 	m_disposed(false),
288 	m_outer(outer),
289 	m_ref(NULL)
290 {
291 	m_threadId = GetCurrentThreadId();
292 }
293 
294 
295 //
296 // ServiceRefImpl::~ServiceRefImpl()
297 //
298 // Deallocate all resources associated with the ServiceRefImpl
299 //
~ServiceRefImpl()300 ServiceRef::ServiceRefImpl::~ServiceRefImpl()
301 {
302 	if (m_socketEvent != NULL)
303 	{
304 		CloseHandle(m_socketEvent);
305 		m_socketEvent = NULL;
306 	}
307 
308 	if (m_stopEvent != NULL)
309 	{
310 		CloseHandle(m_stopEvent);
311 		m_stopEvent = NULL;
312 	}
313 
314 	if (m_ref != NULL)
315 	{
316 		DNSServiceRefDeallocate(m_ref);
317 		m_ref = NULL;
318 	}
319 }
320 
321 
322 //
323 // ServiceRefImpl::SetupEvents()
324 //
325 // Setup the events necessary to manage multi-threaded dispatch
326 // of DNSService Events
327 //
328 void
SetupEvents()329 ServiceRef::ServiceRefImpl::SetupEvents()
330 {
331 	check(m_ref != NULL);
332 
333 	m_socket		=	(SOCKET) DNSServiceRefSockFD(m_ref);
334 	check(m_socket != INVALID_SOCKET);
335 
336 	m_socketEvent	=	CreateEvent(NULL, 0, 0, NULL);
337 
338 	if (m_socketEvent == NULL)
339 	{
340 		throw new DNSServiceException(Unknown);
341 	}
342 
343 	int err = WSAEventSelect(m_socket, m_socketEvent, FD_READ|FD_CLOSE);
344 
345 	if (err != 0)
346 	{
347 		throw new DNSServiceException(Unknown);
348 	}
349 
350 	m_stopEvent = CreateEvent(NULL, 0, 0, NULL);
351 
352 	if (m_stopEvent == NULL)
353 	{
354 		throw new DNSServiceException(Unknown);
355 	}
356 }
357 
358 
359 //
360 // ServiceRefImpl::ProcessingThread()
361 //
362 // Wait for socket events on the DNSServiceRefSockFD().  Also wait
363 // for stop events
364 //
365 void
ProcessingThread()366 ServiceRef::ServiceRefImpl::ProcessingThread()
367 {
368 	check( m_socketEvent != NULL );
369 	check( m_stopEvent != NULL );
370 	check( m_ref != NULL );
371 
372 	HANDLE handles[2];
373 
374 	handles[0] = m_socketEvent;
375 	handles[1] = m_stopEvent;
376 
377 	while (m_disposed == false)
378 	{
379 		int ret = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
380 
381 		//
382 		// it's a socket event
383 		//
384 		if (ret == WAIT_OBJECT_0)
385 		{
386 			DNSServiceProcessResult(m_ref);
387 		}
388 		//
389 		// else it's a stop event
390 		//
391 		else if (ret == WAIT_OBJECT_0 + 1)
392 		{
393 			break;
394 		}
395 		else
396 		{
397 			//
398 			// unexpected wait result
399 			//
400 			dlog( kDebugLevelWarning, DEBUG_NAME "%s: unexpected wait result (result=0x%08X)\n", __ROUTINE__, ret );
401 		}
402 	}
403 
404 	delete this;
405 }
406 
407 
408 //
409 // ServiceRefImpl::Dispose()
410 //
411 // Calls DNSServiceRefDeallocate()
412 //
413 void
Dispose()414 ServiceRef::ServiceRefImpl::Dispose()
415 {
416 	OSStatus	err;
417 	BOOL		ok;
418 
419 	check(m_disposed == false);
420 
421 	m_disposed = true;
422 
423 	ok = SetEvent(m_stopEvent);
424 	err = translate_errno( ok, (OSStatus) GetLastError(), kUnknownErr );
425 	require_noerr( err, exit );
426 
427 exit:
428 
429 	return;
430 }
431 
432 
433 //
434 // ServiceRefImpl::EnumerateDomainsCallback()
435 //
436 // This is the callback from dnssd.dll.  We pass this up to our outer, managed type
437 //
438 void DNSSD_API
EnumerateDomainsCallback(DNSServiceRef sdRef,DNSServiceFlags flags,uint32_t interfaceIndex,DNSServiceErrorType errorCode,const char * replyDomain,void * context)439 ServiceRef::ServiceRefImpl::EnumerateDomainsCallback
440 											(
441 											DNSServiceRef			sdRef,
442 											DNSServiceFlags			flags,
443 											uint32_t				interfaceIndex,
444 											DNSServiceErrorType		errorCode,
445 											const char			*	replyDomain,
446 											void				*	context
447 											)
448 {
449 	ServiceRef::ServiceRefImpl * self = static_cast<ServiceRef::ServiceRefImpl*>(context);
450 
451 	check( self != NULL );
452 	check( self->m_outer != NULL );
453 
454 	if (self->m_disposed == false)
455 	{
456 		self->m_outer->EnumerateDomainsDispatch((ServiceFlags) flags, interfaceIndex, (ErrorCode) errorCode, ConvertToString(replyDomain));
457 	}
458 }
459 
460 
461 //
462 // ServiceRefImpl::RegisterCallback()
463 //
464 // This is the callback from dnssd.dll.  We pass this up to our outer, managed type
465 //
466 void DNSSD_API
RegisterCallback(DNSServiceRef sdRef,DNSServiceFlags flags,DNSServiceErrorType errorCode,const char * name,const char * regtype,const char * domain,void * context)467 ServiceRef::ServiceRefImpl::RegisterCallback
468 							(
469 							DNSServiceRef			sdRef,
470 							DNSServiceFlags			flags,
471 							DNSServiceErrorType		errorCode,
472 							const char			*	name,
473 							const char			*	regtype,
474 							const char			*	domain,
475 							void				*	context
476 							)
477 {
478 	ServiceRef::ServiceRefImpl * self = static_cast<ServiceRef::ServiceRefImpl*>(context);
479 
480 	check( self != NULL );
481 	check( self->m_outer != NULL );
482 
483 	if (self->m_disposed == false)
484 	{
485 		self->m_outer->RegisterDispatch((ServiceFlags) flags, (ErrorCode) errorCode, ConvertToString(name), ConvertToString(regtype), ConvertToString(domain));
486 	}
487 }
488 
489 
490 //
491 // ServiceRefImpl::BrowseCallback()
492 //
493 // This is the callback from dnssd.dll.  We pass this up to our outer, managed type
494 //
495 void DNSSD_API
BrowseCallback(DNSServiceRef sdRef,DNSServiceFlags flags,uint32_t interfaceIndex,DNSServiceErrorType errorCode,const char * serviceName,const char * regtype,const char * replyDomain,void * context)496 ServiceRef::ServiceRefImpl::BrowseCallback
497 							(
498 							DNSServiceRef			sdRef,
499    							DNSServiceFlags			flags,
500 							uint32_t				interfaceIndex,
501 							DNSServiceErrorType		errorCode,
502 							const char			*	serviceName,
503 							const char			*	regtype,
504 							const char			*	replyDomain,
505 							void				*	context
506 							)
507 {
508 	ServiceRef::ServiceRefImpl * self = static_cast<ServiceRef::ServiceRefImpl*>(context);
509 
510 	check( self != NULL );
511 	check( self->m_outer != NULL );
512 
513 	if (self->m_disposed == false)
514 	{
515 		self->m_outer->BrowseDispatch((ServiceFlags) flags, interfaceIndex, (ErrorCode) errorCode, ConvertToString(serviceName), ConvertToString(regtype), ConvertToString(replyDomain));
516 	}
517 }
518 
519 
520 //
521 // ServiceRefImpl::ResolveCallback()
522 //
523 // This is the callback from dnssd.dll.  We pass this up to our outer, managed type
524 //
525 void DNSSD_API
ResolveCallback(DNSServiceRef sdRef,DNSServiceFlags flags,uint32_t interfaceIndex,DNSServiceErrorType errorCode,const char * fullname,const char * hosttarget,uint16_t notAnIntPort,uint16_t txtLen,const char * txtRecord,void * context)526 ServiceRef::ServiceRefImpl::ResolveCallback
527 							(
528 							DNSServiceRef			sdRef,
529 							DNSServiceFlags			flags,
530 							uint32_t				interfaceIndex,
531 							DNSServiceErrorType		errorCode,
532 							const char			*	fullname,
533 							const char			*	hosttarget,
534 							uint16_t				notAnIntPort,
535 							uint16_t				txtLen,
536 							const char			*	txtRecord,
537 							void				*	context
538 							)
539 {
540 	ServiceRef::ServiceRefImpl * self = static_cast<ServiceRef::ServiceRefImpl*>(context);
541 
542 	check( self != NULL );
543 	check( self->m_outer != NULL );
544 
545 	if (self->m_disposed == false)
546 	{
547 		Byte txtRecordBytes[];
548 
549 		txtRecordBytes = NULL;
550 
551 		if (txtLen > 0)
552 		{
553 			//
554 			// copy raw memory into managed byte array
555 			//
556 			txtRecordBytes		=	new Byte[txtLen];
557 			Byte __pin	*	p	=	&txtRecordBytes[0];
558 			memcpy(p, txtRecord, txtLen);
559 		}
560 
561 		self->m_outer->ResolveDispatch((ServiceFlags) flags, interfaceIndex, (ErrorCode) errorCode, ConvertToString(fullname), ConvertToString(hosttarget), ntohs(notAnIntPort), txtRecordBytes);
562 	}
563 }
564 
565 
566 //
567 // ServiceRefImpl::RegisterRecordCallback()
568 //
569 // This is the callback from dnssd.dll.  We pass this up to our outer, managed type
570 //
571 void DNSSD_API
RegisterRecordCallback(DNSServiceRef sdRef,DNSRecordRef rrRef,DNSServiceFlags flags,DNSServiceErrorType errorCode,void * context)572 ServiceRef::ServiceRefImpl::RegisterRecordCallback
573 								(
574 								DNSServiceRef		sdRef,
575 								DNSRecordRef		rrRef,
576 								DNSServiceFlags		flags,
577 								DNSServiceErrorType	errorCode,
578 								void			*	context
579 								)
580 {
581 	ServiceRef::ServiceRefImpl * self = static_cast<ServiceRef::ServiceRefImpl*>(context);
582 
583 	check( self != NULL );
584 	check( self->m_outer != NULL );
585 
586 	if (self->m_disposed == false)
587 	{
588 		RecordRef * record = NULL;
589 
590 		if (errorCode == 0)
591 		{
592 			record = new RecordRef;
593 
594 			record->m_impl->m_ref = rrRef;
595 		}
596 
597 		self->m_outer->RegisterRecordDispatch((ServiceFlags) flags, (ErrorCode) errorCode, record);
598 	}
599 }
600 
601 
602 //
603 // ServiceRefImpl::QueryRecordCallback()
604 //
605 // This is the callback from dnssd.dll.  We pass this up to our outer, managed type
606 //
607 void DNSSD_API
QueryRecordCallback(DNSServiceRef DNSServiceRef,DNSServiceFlags flags,uint32_t interfaceIndex,DNSServiceErrorType errorCode,const char * fullname,uint16_t rrtype,uint16_t rrclass,uint16_t rdlen,const void * rdata,uint32_t ttl,void * context)608 ServiceRef::ServiceRefImpl::QueryRecordCallback
609 								(
610 								DNSServiceRef			DNSServiceRef,
611 								DNSServiceFlags			flags,
612 								uint32_t				interfaceIndex,
613 								DNSServiceErrorType		errorCode,
614 								const char			*	fullname,
615 								uint16_t				rrtype,
616 								uint16_t				rrclass,
617 								uint16_t				rdlen,
618 								const void			*	rdata,
619 								uint32_t				ttl,
620 								void				*	context
621 								)
622 {
623 	ServiceRef::ServiceRefImpl * self = static_cast<ServiceRef::ServiceRefImpl*>(context);
624 
625 	check( self != NULL );
626 	check( self->m_outer != NULL );
627 
628 	if (self->m_disposed == false)
629 	{
630 		Byte rdataBytes[];
631 
632 		if (rdlen)
633 		{
634 			rdataBytes			=	new Byte[rdlen];
635 			Byte __pin * p		=	&rdataBytes[0];
636 			memcpy(p, rdata, rdlen);
637 		}
638 
639 		self->m_outer->QueryRecordDispatch((ServiceFlags) flags, (int) interfaceIndex, (ErrorCode) errorCode, ConvertToString(fullname), rrtype, rrclass, rdataBytes, ttl);
640 	}
641 }
642 
643 
644 /*
645  * EnumerateDomains()
646  *
647  * This maps to DNSServiceEnumerateDomains().  Returns an
648  * initialized ServiceRef on success, throws an exception
649  * on failure.
650  */
651 ServiceRef*
EnumerateDomains(int flags,int interfaceIndex,EnumerateDomainsReply * callback)652 DNSService::EnumerateDomains
653 		(
654 		int							flags,
655 		int							interfaceIndex,
656 		EnumerateDomainsReply	*	callback
657 		)
658 {
659 	ServiceRef * sdRef = new ServiceRef(callback);
660 	int			 err;
661 
662 	err = DNSServiceEnumerateDomains(&sdRef->m_impl->m_ref, flags, interfaceIndex, ServiceRef::ServiceRefImpl::EnumerateDomainsCallback, sdRef->m_impl);
663 
664 	if (err != 0)
665 	{
666 		throw new DNSServiceException(err);
667 	}
668 
669 	sdRef->StartThread();
670 
671 	return sdRef;
672 }
673 
674 
675 /*
676  * Register()
677  *
678  * This maps to DNSServiceRegister().  Returns an
679  * initialized ServiceRef on success, throws an exception
680  * on failure.
681  */
682 ServiceRef*
Register(int flags,int interfaceIndex,String * name,String * regtype,String * domain,String * host,int port,Byte txtRecord[],RegisterReply * callback)683 DNSService::Register
684 				(
685 				int					flags,
686 				int					interfaceIndex,
687 				String			*	name,
688 				String			*	regtype,
689 				String			*	domain,
690 				String			*	host,
691 				int					port,
692 				Byte				txtRecord[],
693 				RegisterReply	*	callback
694 				)
695 {
696 	ServiceRef	*	sdRef	=	new ServiceRef(callback);
697 	PString		*	pName	=	new PString(name);
698 	PString		*	pType	=	new PString(regtype);
699 	PString		*	pDomain =	new PString(domain);
700 	PString		*	pHost	=	new PString(host);
701 	int				len		=	0;
702 	Byte __pin	*	p		=	NULL;
703 	void		*	v		=	NULL;
704 
705 	if ((txtRecord != NULL) && (txtRecord->Length > 0))
706 	{
707 		len		= txtRecord->Length;
708 		p		= &txtRecord[0];
709 		v		= (void*) p;
710 	}
711 
712 	int err = DNSServiceRegister(&sdRef->m_impl->m_ref, flags, interfaceIndex, pName->c_str(), pType->c_str(), pDomain->c_str(), pHost->c_str(), htons(port), len, v, ServiceRef::ServiceRefImpl::RegisterCallback, sdRef->m_impl );
713 
714 	if (err != 0)
715 	{
716 		throw new DNSServiceException(err);
717 	}
718 
719 	sdRef->StartThread();
720 
721 	return sdRef;
722 }
723 
724 
725 /*
726  * AddRecord()
727  *
728  * This maps to DNSServiceAddRecord().  Returns an
729  * initialized ServiceRef on success, throws an exception
730  * on failure.
731  */
732 RecordRef*
AddRecord(ServiceRef * sdRef,int flags,int rrtype,Byte rdata[],int ttl)733 DNSService::AddRecord
734 				(
735 				ServiceRef	*	sdRef,
736 				int				flags,
737 				int				rrtype,
738 				Byte			rdata[],
739 				int				ttl
740 				)
741 {
742 	int				len		=	0;
743 	Byte __pin	*	p		=	NULL;
744 	void		*	v		=	NULL;
745 
746 	if ((rdata != NULL) && (rdata->Length > 0))
747 	{
748 		len = rdata->Length;
749 		p	= &rdata[0];
750 		v	= (void*) p;
751 	}
752 
753 	RecordRef * record = new RecordRef;
754 
755 	int err = DNSServiceAddRecord(sdRef->m_impl->m_ref, &record->m_impl->m_ref, flags, rrtype, len, v, ttl);
756 
757 	if (err != 0)
758 	{
759 		throw new DNSServiceException(err);
760 	}
761 
762 	return record;
763 }
764 
765 
766 /*
767  * UpdateRecord()
768  *
769  * This maps to DNSServiceUpdateRecord().  Returns an
770  * initialized ServiceRef on success, throws an exception
771  * on failure.
772  */
773 void
UpdateRecord(ServiceRef * sdRef,RecordRef * record,int flags,Byte rdata[],int ttl)774 DNSService::UpdateRecord
775 				(
776 				ServiceRef	*	sdRef,
777 				RecordRef	*	record,
778 				int				flags,
779 				Byte			rdata[],
780 				int				ttl
781 				)
782 {
783 	int				len		=	0;
784 	Byte __pin	*	p		=	NULL;
785 	void		*	v		=	NULL;
786 
787 	if ((rdata != NULL) && (rdata->Length > 0))
788 	{
789 		len	= rdata->Length;
790 		p	= &rdata[0];
791 		v	= (void*) p;
792 	}
793 
794 	int err = DNSServiceUpdateRecord(sdRef->m_impl->m_ref, record ? record->m_impl->m_ref : NULL, flags, len, v, ttl);
795 
796 	if (err != 0)
797 	{
798 		throw new DNSServiceException(err);
799 	}
800 }
801 
802 
803 /*
804  * RemoveRecord()
805  *
806  * This maps to DNSServiceRemoveRecord().  Returns an
807  * initialized ServiceRef on success, throws an exception
808  * on failure.
809  */
810 void
RemoveRecord(ServiceRef * sdRef,RecordRef * record,int flags)811 DNSService::RemoveRecord
812 		(
813 		ServiceRef	*	sdRef,
814 		RecordRef	*	record,
815 		int				flags
816 		)
817 {
818 	int err = DNSServiceRemoveRecord(sdRef->m_impl->m_ref, record->m_impl->m_ref, flags);
819 
820 	if (err != 0)
821 	{
822 		throw new DNSServiceException(err);
823 	}
824 }
825 
826 
827 /*
828  * Browse()
829  *
830  * This maps to DNSServiceBrowse().  Returns an
831  * initialized ServiceRef on success, throws an exception
832  * on failure.
833  */
834 ServiceRef*
Browse(int flags,int interfaceIndex,String * regtype,String * domain,BrowseReply * callback)835 DNSService::Browse
836 	(
837 	int				flags,
838 	int				interfaceIndex,
839 	String		*	regtype,
840 	String		*	domain,
841 	BrowseReply	*	callback
842 	)
843 {
844 	ServiceRef	*	sdRef	= new ServiceRef(callback);
845 	PString		*	pType	= new PString(regtype);
846 	PString		*	pDomain	= new PString(domain);
847 
848 	int err = DNSServiceBrowse(&sdRef->m_impl->m_ref, flags, interfaceIndex, pType->c_str(), pDomain->c_str(),(DNSServiceBrowseReply) ServiceRef::ServiceRefImpl::BrowseCallback, sdRef->m_impl);
849 
850 	if (err != 0)
851 	{
852 		throw new DNSServiceException(err);
853 	}
854 
855 	sdRef->StartThread();
856 
857 	return sdRef;
858 }
859 
860 
861 /*
862  * Resolve()
863  *
864  * This maps to DNSServiceResolve().  Returns an
865  * initialized ServiceRef on success, throws an exception
866  * on failure.
867  */
868 ServiceRef*
Resolve(int flags,int interfaceIndex,String * name,String * regtype,String * domain,ResolveReply * callback)869 DNSService::Resolve
870 	(
871 	int					flags,
872 	int					interfaceIndex,
873 	String			*	name,
874 	String			*	regtype,
875 	String			*	domain,
876 	ResolveReply	*	callback
877 	)
878 {
879 	ServiceRef	*	sdRef	= new ServiceRef(callback);
880 	PString		*	pName	= new PString(name);
881 	PString		*	pType	= new PString(regtype);
882 	PString		*	pDomain	= new PString(domain);
883 
884 	int err = DNSServiceResolve(&sdRef->m_impl->m_ref, flags, interfaceIndex, pName->c_str(), pType->c_str(), pDomain->c_str(),(DNSServiceResolveReply) ServiceRef::ServiceRefImpl::ResolveCallback, sdRef->m_impl);
885 
886 	if (err != 0)
887 	{
888 		throw new DNSServiceException(err);
889 	}
890 
891 	sdRef->StartThread();
892 
893 	return sdRef;
894 }
895 
896 
897 /*
898  * CreateConnection()
899  *
900  * This maps to DNSServiceCreateConnection().  Returns an
901  * initialized ServiceRef on success, throws an exception
902  * on failure.
903  */
904 ServiceRef*
CreateConnection(RegisterRecordReply * callback)905 DNSService::CreateConnection
906 			(
907 			RegisterRecordReply * callback
908 			)
909 {
910 	ServiceRef * sdRef = new ServiceRef(callback);
911 
912 	int err = DNSServiceCreateConnection(&sdRef->m_impl->m_ref);
913 
914 	if (err != 0)
915 	{
916 		throw new DNSServiceException(err);
917 	}
918 
919 	sdRef->StartThread();
920 
921 	return sdRef;
922 }
923 
924 
925 /*
926  * RegisterRecord()
927  *
928  * This maps to DNSServiceRegisterRecord().  Returns an
929  * initialized ServiceRef on success, throws an exception
930  * on failure.
931  */
932 
933 RecordRef*
RegisterRecord(ServiceRef * sdRef,ServiceFlags flags,int interfaceIndex,String * fullname,int rrtype,int rrclass,Byte rdata[],int ttl)934 DNSService::RegisterRecord
935 			(
936 			ServiceRef			*	sdRef,
937 			ServiceFlags			flags,
938 			int						interfaceIndex,
939 			String				*	fullname,
940 			int						rrtype,
941 			int						rrclass,
942 			Byte					rdata[],
943 			int						ttl
944 			)
945 {
946 	RecordRef	*	record	= new RecordRef;
947 	int				len		= 0;
948 	Byte __pin	*	p		= NULL;
949 	void		*	v		= NULL;
950 
951 	PString * pFullname = new PString(fullname);
952 
953 	if ((rdata != NULL) && (rdata->Length > 0))
954 	{
955 		len		= rdata->Length;
956 		p		= &rdata[0];
957 		v		= (void*) p;
958 	}
959 
960 	int err = DNSServiceRegisterRecord(sdRef->m_impl->m_ref, &record->m_impl->m_ref, flags, interfaceIndex, pFullname->c_str(), rrtype, rrclass, len, v, ttl, (DNSServiceRegisterRecordReply) ServiceRef::ServiceRefImpl::RegisterRecordCallback, sdRef->m_impl);
961 
962 	if (err != 0)
963 	{
964 		throw new DNSServiceException(err);
965 	}
966 
967 	return record;
968 }
969 
970 /*
971  * QueryRecord()
972  *
973  * This maps to DNSServiceQueryRecord().  Returns an
974  * initialized ServiceRef on success, throws an exception
975  * on failure.
976  */
977 ServiceRef*
QueryRecord(ServiceFlags flags,int interfaceIndex,String * fullname,int rrtype,int rrclass,QueryRecordReply * callback)978 DNSService::QueryRecord
979 		(
980 		ServiceFlags			flags,
981 		int						interfaceIndex,
982 		String				*	fullname,
983 		int						rrtype,
984 		int						rrclass,
985 		QueryRecordReply	*	callback
986 		)
987 {
988 	ServiceRef	*	sdRef		= new ServiceRef(callback);
989 	PString		*	pFullname	= new PString(fullname);
990 
991 	int err = DNSServiceQueryRecord(&sdRef->m_impl->m_ref, flags, interfaceIndex, pFullname->c_str(), rrtype, rrclass, (DNSServiceQueryRecordReply) ServiceRef::ServiceRefImpl::QueryRecordCallback, sdRef->m_impl);
992 
993 	if (err != 0)
994 	{
995 		throw new DNSServiceException(err);
996 	}
997 
998 	sdRef->StartThread();
999 
1000 	return sdRef;
1001 }
1002 
1003 
1004 /*
1005  * ReconfirmRecord()
1006  *
1007  * This maps to DNSServiceReconfirmRecord().  Returns an
1008  * initialized ServiceRef on success, throws an exception
1009  * on failure.
1010  */
1011 void
ReconfirmRecord(ServiceFlags flags,int interfaceIndex,String * fullname,int rrtype,int rrclass,Byte rdata[])1012 DNSService::ReconfirmRecord
1013 		(
1014 		ServiceFlags	flags,
1015 		int				interfaceIndex,
1016 		String		*	fullname,
1017 		int				rrtype,
1018 		int				rrclass,
1019 		Byte			rdata[]
1020 		)
1021 {
1022 	int				len	= 0;
1023 	Byte __pin	*	p	= NULL;
1024 	void		*	v	= NULL;
1025 
1026 	PString * pFullname = new PString(fullname);
1027 
1028 	if ((rdata != NULL) && (rdata->Length > 0))
1029 	{
1030 		len	= rdata->Length;
1031 		p	= &rdata[0];
1032 		v	= (void*) p;
1033 	}
1034 
1035 	DNSServiceReconfirmRecord(flags, interfaceIndex, pFullname->c_str(), rrtype, rrclass, len, v);
1036 }
1037 
1038 
1039 void
SetValue(String * key,Byte value[])1040 TextRecord::SetValue
1041 		(
1042 		String	*	key,
1043 		Byte		value[]            /* may be NULL */
1044 		)
1045 {
1046 	PString			*	pKey = new PString(key);
1047 	int					len		=	0;
1048 	Byte __pin		*	p		=	NULL;
1049 	void			*	v		=	NULL;
1050 	DNSServiceErrorType	err;
1051 
1052 	if (value && (value->Length > 0))
1053 	{
1054 		len	=	value->Length;
1055 		p	=	&value[0];
1056 		v	=	(void*) p;
1057 	}
1058 
1059 	err = TXTRecordSetValue(&m_impl->m_ref, pKey->c_str(), len, v);
1060 
1061 	if (err != 0)
1062 	{
1063 		throw new DNSServiceException(err);
1064 	}
1065 }
1066 
1067 
1068 void
RemoveValue(String * key)1069 TextRecord::RemoveValue
1070 		(
1071 		String	*	key
1072 		)
1073 {
1074 	PString			*	pKey = new PString(key);
1075 	DNSServiceErrorType	err;
1076 
1077 	err = TXTRecordRemoveValue(&m_impl->m_ref, pKey->c_str());
1078 
1079 	if (err != 0)
1080 	{
1081 		throw new DNSServiceException(err);
1082 	}
1083 }
1084 
1085 
1086 int
GetLength()1087 TextRecord::GetLength
1088 		(
1089 		)
1090 {
1091 	return TXTRecordGetLength(&m_impl->m_ref);
1092 }
1093 
1094 
1095 Byte
1096 TextRecord::GetBytes
1097 		(
1098 		) __gc[]
1099 {
1100 	const void	*	noGCBytes = NULL;
1101 	Byte			gcBytes[] = NULL;
1102 
1103 	noGCBytes		=	TXTRecordGetBytesPtr(&m_impl->m_ref);
1104 	int			len	=	GetLength();
1105 
1106 	if (noGCBytes && len)
1107 	{
1108 		gcBytes				=	new Byte[len];
1109 		Byte __pin	*	p	=	&gcBytes[0];
1110 		memcpy(p, noGCBytes, len);
1111 	}
1112 
1113 	return gcBytes;
1114 }
1115 
1116 
1117 bool
1118 TextRecord::ContainsKey
1119 		(
1120 		Byte		txtRecord[],
1121 		String	*	key
1122 		)
1123 {
1124 	PString		*	pKey	= new PString(key);
1125 	Byte __pin	*	p		= &txtRecord[0];
1126 
1127 	return (TXTRecordContainsKey(txtRecord->Length, p, pKey->c_str()) > 0) ? true : false;
1128 }
1129 
1130 
1131 Byte
1132 TextRecord::GetValueBytes
1133 		(
1134 		Byte		txtRecord[],
1135 		String	*	key
1136 		) __gc[]
1137 {
1138 	uint8_t			valueLen;
1139 	Byte			ret[]	= NULL;
1140 	PString		*	pKey	= new PString(key);
1141 	Byte __pin	*	p1		= &txtRecord[0];
1142 	const void	*	v;
1143 
1144 	v = TXTRecordGetValuePtr(txtRecord->Length, p1, pKey->c_str(), &valueLen);
1145 
1146 	if (v != NULL)
1147 	{
1148 		ret					= new Byte[valueLen];
1149 		Byte __pin	*	p2	= &ret[0];
1150 
1151 		memcpy(p2, v, valueLen);
1152 	}
1153 
1154 	return ret;
1155 }
1156 
1157 
1158 int
1159 TextRecord::GetCount
1160 		(
1161 		Byte txtRecord[]
1162 		)
1163 {
1164 	Byte __pin	*	p	= &txtRecord[0];
1165 
1166 	return TXTRecordGetCount(txtRecord->Length, p);
1167 }
1168 
1169 
1170 Byte
1171 TextRecord::GetItemAtIndex
1172 		(
1173 		Byte				txtRecord[],
1174 		int					index,
1175 		[Out] String	**	key
1176 		) __gc[]
1177 {
1178 	char				keyBuf[255];
1179 	uint8_t				keyBufLen = 255;
1180 	uint8_t				valueLen;
1181 	void			*	value;
1182 	Byte				ret[]	= NULL;
1183 	DNSServiceErrorType	err;
1184 	Byte __pin		*	p1		= &txtRecord[0];
1185 
1186 
1187 	err = TXTRecordGetItemAtIndex(txtRecord->Length, p1, index, keyBufLen, keyBuf, &valueLen, (const void**) &value);
1188 
1189 	if (err != 0)
1190 	{
1191 		throw new DNSServiceException(err);
1192 	}
1193 
1194 	*key = ConvertToString(keyBuf);
1195 
1196 	if (valueLen)
1197 	{
1198 		ret					= new Byte[valueLen];
1199 		Byte __pin	*	p2	= &ret[0];
1200 
1201 		memcpy(p2, value, valueLen);
1202 	}
1203 
1204 	return ret;
1205 }
1206 
1207 
1208 //
1209 // DNSServiceException::DNSServiceException()
1210 //
1211 // Constructs an exception with an error code
1212 //
1213 DNSServiceException::DNSServiceException
1214 				(
1215 				int _err
1216 				)
1217 :
1218 	err(_err)
1219 {
1220 }
1221 
1222 
1223 //
1224 // This version of the constructor is useful for instances in which
1225 // an inner exception is thrown, caught, and then a new exception
1226 // is thrown in it's place
1227 //
DNSServiceException(String * message,System::Exception * innerException)1228 DNSServiceException::DNSServiceException
1229 				(
1230 				String				*	message,
1231 				System::Exception	*	innerException
1232 				)
1233 {
1234 }
1235