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
27using namespace System::Net::Sockets;
28using namespace System::Diagnostics;
29using namespace Apple;
30using namespace Apple::DNSSD;
31
32
33//===========================================================================================================================
34//	Constants
35//===========================================================================================================================
36
37#define	DEBUG_NAME	"[dnssd.NET] "
38
39//
40// ConvertToString
41//
42static String*
43ConvertToString(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//
57ServiceRef::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
67ServiceRef::~ServiceRef()
68{
69}
70
71
72//
73// StartThread
74//
75// Starts the main processing thread
76//
77void
78ServiceRef::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//
98void
99ServiceRef::ProcessingThread()
100{
101	m_impl->ProcessingThread();
102}
103
104
105//
106// Dispose
107//
108// Calls impl-Dispose().  This ultimately will call DNSServiceRefDeallocate()
109//
110void
111ServiceRef::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//
140void
141ServiceRef::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//
162void
163ServiceRef::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//
185void
186ServiceRef::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//
209void
210ServiceRef::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//
234void
235ServiceRef::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//
255void
256ServiceRef::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//
283ServiceRef::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//
300ServiceRef::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//
328void
329ServiceRef::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//
365void
366ServiceRef::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//
413void
414ServiceRef::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
427exit:
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//
438void DNSSD_API
439ServiceRef::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//
466void DNSSD_API
467ServiceRef::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//
495void DNSSD_API
496ServiceRef::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//
525void DNSSD_API
526ServiceRef::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//
571void DNSSD_API
572ServiceRef::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//
607void DNSSD_API
608ServiceRef::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 */
651ServiceRef*
652DNSService::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 */
682ServiceRef*
683DNSService::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 */
732RecordRef*
733DNSService::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 */
773void
774DNSService::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 */
810void
811DNSService::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 */
834ServiceRef*
835DNSService::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 */
868ServiceRef*
869DNSService::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 */
904ServiceRef*
905DNSService::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
933RecordRef*
934DNSService::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 */
977ServiceRef*
978DNSService::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 */
1011void
1012DNSService::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
1039void
1040TextRecord::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
1068void
1069TextRecord::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
1086int
1087TextRecord::GetLength
1088		(
1089		)
1090{
1091	return TXTRecordGetLength(&m_impl->m_ref);
1092}
1093
1094
1095Byte
1096TextRecord::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
1117bool
1118TextRecord::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
1131Byte
1132TextRecord::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
1158int
1159TextRecord::GetCount
1160		(
1161		Byte txtRecord[]
1162		)
1163{
1164	Byte __pin	*	p	= &txtRecord[0];
1165
1166	return TXTRecordGetCount(txtRecord->Length, p);
1167}
1168
1169
1170Byte
1171TextRecord::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//
1213DNSServiceException::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//
1228DNSServiceException::DNSServiceException
1229				(
1230				String				*	message,
1231				System::Exception	*	innerException
1232				)
1233{
1234}
1235