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