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* 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 // 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 67 ServiceRef::~ServiceRef() 68 { 69 } 70 71 72 // 73 // StartThread 74 // 75 // Starts the main processing thread 76 // 77 void 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 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 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 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 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 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 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 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 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 // 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 // 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 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 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 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 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 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 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 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 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 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* 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* 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* 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 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 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* 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* 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* 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* 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* 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 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 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 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 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 // 1228 DNSServiceException::DNSServiceException 1229 ( 1230 String * message, 1231 System::Exception * innerException 1232 ) 1233 { 1234 } 1235