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