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