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