1 // DNSSD.cpp : Implementation of CDNSSD 2 3 #include "stdafx.h" 4 #include "DNSSD.h" 5 #include "DNSSDService.h" 6 #include "TXTRecord.h" 7 #include <dns_sd.h> 8 #include <CommonServices.h> 9 #include <DebugServices.h> 10 #include "StringServices.h" 11 12 13 // CDNSSD 14 15 STDMETHODIMP CDNSSD::Browse(DNSSDFlags flags, ULONG ifIndex, BSTR regtype, BSTR domain, IBrowseListener* listener, IDNSSDService** browser ) 16 { 17 CComObject<CDNSSDService> * object = NULL; 18 std::string regtypeUTF8; 19 std::string domainUTF8; 20 DNSServiceRef sref = NULL; 21 DNSServiceErrorType err = 0; 22 HRESULT hr = 0; 23 BOOL ok; 24 25 // Initialize 26 *browser = NULL; 27 28 // Convert BSTR params to utf8 29 ok = BSTRToUTF8( regtype, regtypeUTF8 ); 30 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 31 ok = BSTRToUTF8( domain, domainUTF8 ); 32 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 33 34 try 35 { 36 object = new CComObject<CDNSSDService>(); 37 } 38 catch ( ... ) 39 { 40 object = NULL; 41 } 42 43 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory ); 44 hr = object->FinalConstruct(); 45 require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown ); 46 object->AddRef(); 47 48 err = DNSServiceBrowse( &sref, flags, ifIndex, regtypeUTF8.c_str(), domainUTF8.c_str(), ( DNSServiceBrowseReply ) &BrowseReply, object ); 49 require_noerr( err, exit ); 50 51 object->SetServiceRef( sref ); 52 object->SetListener( listener ); 53 54 err = object->Run(); 55 require_noerr( err, exit ); 56 57 *browser = object; 58 59 exit: 60 61 if ( err && object ) 62 { 63 object->Release(); 64 } 65 66 return err; 67 } 68 69 70 STDMETHODIMP CDNSSD::Resolve(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, IResolveListener* listener, IDNSSDService** service) 71 { 72 CComObject<CDNSSDService> * object = NULL; 73 std::string serviceNameUTF8; 74 std::string regTypeUTF8; 75 std::string domainUTF8; 76 DNSServiceRef sref = NULL; 77 DNSServiceErrorType err = 0; 78 HRESULT hr = 0; 79 BOOL ok; 80 81 // Initialize 82 *service = NULL; 83 84 // Convert BSTR params to utf8 85 ok = BSTRToUTF8( serviceName, serviceNameUTF8 ); 86 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 87 ok = BSTRToUTF8( regType, regTypeUTF8 ); 88 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 89 ok = BSTRToUTF8( domain, domainUTF8 ); 90 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 91 92 try 93 { 94 object = new CComObject<CDNSSDService>(); 95 } 96 catch ( ... ) 97 { 98 object = NULL; 99 } 100 101 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory ); 102 hr = object->FinalConstruct(); 103 require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown ); 104 object->AddRef(); 105 106 err = DNSServiceResolve( &sref, flags, ifIndex, serviceNameUTF8.c_str(), regTypeUTF8.c_str(), domainUTF8.c_str(), ( DNSServiceResolveReply ) &ResolveReply, object ); 107 require_noerr( err, exit ); 108 109 object->SetServiceRef( sref ); 110 object->SetListener( listener ); 111 112 err = object->Run(); 113 require_noerr( err, exit ); 114 115 *service = object; 116 117 exit: 118 119 if ( err && object ) 120 { 121 object->Release(); 122 } 123 124 return err; 125 } 126 127 128 STDMETHODIMP CDNSSD::EnumerateDomains(DNSSDFlags flags, ULONG ifIndex, IDomainListener *listener, IDNSSDService **service) 129 { 130 CComObject<CDNSSDService> * object = NULL; 131 DNSServiceRef sref = NULL; 132 DNSServiceErrorType err = 0; 133 HRESULT hr = 0; 134 135 // Initialize 136 *service = NULL; 137 138 try 139 { 140 object = new CComObject<CDNSSDService>(); 141 } 142 catch ( ... ) 143 { 144 object = NULL; 145 } 146 147 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory ); 148 hr = object->FinalConstruct(); 149 require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown ); 150 object->AddRef(); 151 152 err = DNSServiceEnumerateDomains( &sref, flags, ifIndex, ( DNSServiceDomainEnumReply ) &DomainEnumReply, object ); 153 require_noerr( err, exit ); 154 155 object->SetServiceRef( sref ); 156 object->SetListener( listener ); 157 158 err = object->Run(); 159 require_noerr( err, exit ); 160 161 *service = object; 162 163 exit: 164 165 if ( err && object ) 166 { 167 object->Release(); 168 } 169 170 return err; 171 } 172 173 174 STDMETHODIMP CDNSSD::Register(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, BSTR host, USHORT port, ITXTRecord *record, IRegisterListener *listener, IDNSSDService **service) 175 { 176 CComObject<CDNSSDService> * object = NULL; 177 std::string serviceNameUTF8; 178 std::string regTypeUTF8; 179 std::string domainUTF8; 180 std::string hostUTF8; 181 const void * txtRecord = NULL; 182 uint16_t txtLen = 0; 183 DNSServiceRef sref = NULL; 184 DNSServiceErrorType err = 0; 185 HRESULT hr = 0; 186 BOOL ok; 187 188 // Initialize 189 *service = NULL; 190 191 // Convert BSTR params to utf8 192 ok = BSTRToUTF8( serviceName, serviceNameUTF8 ); 193 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 194 ok = BSTRToUTF8( regType, regTypeUTF8 ); 195 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 196 ok = BSTRToUTF8( domain, domainUTF8 ); 197 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 198 ok = BSTRToUTF8( host, hostUTF8 ); 199 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 200 201 try 202 { 203 object = new CComObject<CDNSSDService>(); 204 } 205 catch ( ... ) 206 { 207 object = NULL; 208 } 209 210 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory ); 211 hr = object->FinalConstruct(); 212 require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown ); 213 object->AddRef(); 214 215 if ( record ) 216 { 217 CComObject< CTXTRecord > * realTXTRecord; 218 219 realTXTRecord = ( CComObject< CTXTRecord >* ) record; 220 221 txtRecord = realTXTRecord->GetBytes(); 222 txtLen = realTXTRecord->GetLen(); 223 } 224 225 err = DNSServiceRegister( &sref, flags, ifIndex, serviceNameUTF8.c_str(), regTypeUTF8.c_str(), domainUTF8.c_str(), hostUTF8.c_str(), port, txtLen, txtRecord, ( DNSServiceRegisterReply ) &RegisterReply, object ); 226 require_noerr( err, exit ); 227 228 object->SetServiceRef( sref ); 229 object->SetListener( listener ); 230 231 err = object->Run(); 232 require_noerr( err, exit ); 233 234 *service = object; 235 236 exit: 237 238 if ( err && object ) 239 { 240 object->Release(); 241 } 242 243 return err; 244 } 245 246 247 STDMETHODIMP CDNSSD::QueryRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullname, DNSSDRRType rrtype, DNSSDRRClass rrclass, IQueryRecordListener *listener, IDNSSDService **service) 248 { 249 CComObject<CDNSSDService> * object = NULL; 250 DNSServiceRef sref = NULL; 251 std::string fullNameUTF8; 252 DNSServiceErrorType err = 0; 253 HRESULT hr = 0; 254 BOOL ok; 255 256 // Initialize 257 *service = NULL; 258 259 // Convert BSTR params to utf8 260 ok = BSTRToUTF8( fullname, fullNameUTF8 ); 261 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 262 263 try 264 { 265 object = new CComObject<CDNSSDService>(); 266 } 267 catch ( ... ) 268 { 269 object = NULL; 270 } 271 272 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory ); 273 hr = object->FinalConstruct(); 274 require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown ); 275 object->AddRef(); 276 277 err = DNSServiceQueryRecord( &sref, flags, ifIndex, fullNameUTF8.c_str(), ( uint16_t ) rrtype, ( uint16_t ) rrclass, ( DNSServiceQueryRecordReply ) &QueryRecordReply, object ); 278 require_noerr( err, exit ); 279 280 object->SetServiceRef( sref ); 281 object->SetListener( listener ); 282 283 err = object->Run(); 284 require_noerr( err, exit ); 285 286 *service = object; 287 288 exit: 289 290 if ( err && object ) 291 { 292 object->Release(); 293 } 294 295 return err; 296 } 297 298 299 STDMETHODIMP CDNSSD::GetAddrInfo(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, BSTR hostName, IGetAddrInfoListener *listener, IDNSSDService **service) 300 { 301 CComObject<CDNSSDService> * object = NULL; 302 DNSServiceRef sref = NULL; 303 std::string hostNameUTF8; 304 DNSServiceErrorType err = 0; 305 HRESULT hr = 0; 306 BOOL ok; 307 308 // Initialize 309 *service = NULL; 310 311 // Convert BSTR params to utf8 312 ok = BSTRToUTF8( hostName, hostNameUTF8 ); 313 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 314 315 try 316 { 317 object = new CComObject<CDNSSDService>(); 318 } 319 catch ( ... ) 320 { 321 object = NULL; 322 } 323 324 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory ); 325 hr = object->FinalConstruct(); 326 require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown ); 327 object->AddRef(); 328 329 err = DNSServiceGetAddrInfo( &sref, flags, ifIndex, addressFamily, hostNameUTF8.c_str(), ( DNSServiceGetAddrInfoReply ) &GetAddrInfoReply, object ); 330 require_noerr( err, exit ); 331 332 object->SetServiceRef( sref ); 333 object->SetListener( listener ); 334 335 err = object->Run(); 336 require_noerr( err, exit ); 337 338 *service = object; 339 340 exit: 341 342 if ( err && object ) 343 { 344 object->Release(); 345 } 346 347 return err; 348 } 349 350 351 STDMETHODIMP CDNSSD::CreateConnection(IDNSSDService **service) 352 { 353 CComObject<CDNSSDService> * object = NULL; 354 DNSServiceRef sref = NULL; 355 DNSServiceErrorType err = 0; 356 HRESULT hr = 0; 357 358 // Initialize 359 *service = NULL; 360 361 try 362 { 363 object = new CComObject<CDNSSDService>(); 364 } 365 catch ( ... ) 366 { 367 object = NULL; 368 } 369 370 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory ); 371 hr = object->FinalConstruct(); 372 require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown ); 373 object->AddRef(); 374 375 err = DNSServiceCreateConnection( &sref ); 376 require_noerr( err, exit ); 377 378 object->SetServiceRef( sref ); 379 380 *service = object; 381 382 exit: 383 384 if ( err && object ) 385 { 386 object->Release(); 387 } 388 389 return err; 390 } 391 392 393 STDMETHODIMP CDNSSD::NATPortMappingCreate(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, DNSSDProtocol protocol, USHORT internalPort, USHORT externalPort, ULONG ttl, INATPortMappingListener *listener, IDNSSDService **service) 394 { 395 CComObject<CDNSSDService> * object = NULL; 396 DNSServiceRef sref = NULL; 397 DNSServiceProtocol prot = 0; 398 DNSServiceErrorType err = 0; 399 HRESULT hr = 0; 400 401 // Initialize 402 *service = NULL; 403 404 try 405 { 406 object = new CComObject<CDNSSDService>(); 407 } 408 catch ( ... ) 409 { 410 object = NULL; 411 } 412 413 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory ); 414 hr = object->FinalConstruct(); 415 require_action( hr == S_OK, exit, err = kDNSServiceErr_Unknown ); 416 object->AddRef(); 417 418 prot = ( addressFamily | protocol ); 419 420 err = DNSServiceNATPortMappingCreate( &sref, flags, ifIndex, prot, internalPort, externalPort, ttl, ( DNSServiceNATPortMappingReply ) &NATPortMappingReply, object ); 421 require_noerr( err, exit ); 422 423 object->SetServiceRef( sref ); 424 object->SetListener( listener ); 425 426 err = object->Run(); 427 require_noerr( err, exit ); 428 429 *service = object; 430 431 exit: 432 433 if ( err && object ) 434 { 435 object->Release(); 436 } 437 438 return err; 439 } 440 441 442 STDMETHODIMP CDNSSD::GetProperty(BSTR prop, VARIANT * value ) 443 { 444 std::string propUTF8; 445 std::vector< BYTE > byteArray; 446 SAFEARRAY * psa = NULL; 447 BYTE * pData = NULL; 448 uint32_t elems = 0; 449 DNSServiceErrorType err = 0; 450 BOOL ok = TRUE; 451 452 // Convert BSTR params to utf8 453 ok = BSTRToUTF8( prop, propUTF8 ); 454 require_action( ok, exit, err = kDNSServiceErr_BadParam ); 455 456 // Setup the byte array 457 require_action( V_VT( value ) == ( VT_ARRAY|VT_UI1 ), exit, err = kDNSServiceErr_Unknown ); 458 psa = V_ARRAY( value ); 459 require_action( psa, exit, err = kDNSServiceErr_Unknown ); 460 require_action( SafeArrayGetDim( psa ) == 1, exit, err = kDNSServiceErr_Unknown ); 461 byteArray.reserve( psa->rgsabound[0].cElements ); 462 byteArray.assign( byteArray.capacity(), 0 ); 463 elems = ( uint32_t ) byteArray.capacity(); 464 465 // Call the function and package the return value in the Variant 466 err = DNSServiceGetProperty( propUTF8.c_str(), &byteArray[ 0 ], &elems ); 467 require_noerr( err, exit ); 468 ok = ByteArrayToVariant( &byteArray[ 0 ], elems, value ); 469 require_action( ok, exit, err = kDNSSDError_Unknown ); 470 471 exit: 472 473 if ( psa ) 474 { 475 SafeArrayUnaccessData( psa ); 476 psa = NULL; 477 } 478 479 return err; 480 } 481 482 483 void DNSSD_API 484 CDNSSD::DomainEnumReply 485 ( 486 DNSServiceRef sdRef, 487 DNSServiceFlags flags, 488 uint32_t ifIndex, 489 DNSServiceErrorType errorCode, 490 const char *replyDomainUTF8, 491 void *context 492 ) 493 { 494 CComObject<CDNSSDService> * service; 495 int err; 496 497 service = ( CComObject< CDNSSDService>* ) context; 498 require_action( service, exit, err = kDNSServiceErr_Unknown ); 499 500 if ( !service->Stopped() ) 501 { 502 IDomainListener * listener; 503 504 listener = ( IDomainListener* ) service->GetListener(); 505 require_action( listener, exit, err = kDNSServiceErr_Unknown ); 506 507 if ( !errorCode ) 508 { 509 CComBSTR replyDomain; 510 511 UTF8ToBSTR( replyDomainUTF8, replyDomain ); 512 513 if ( flags & kDNSServiceFlagsAdd ) 514 { 515 listener->DomainFound( service, ( DNSSDFlags ) flags, ifIndex, replyDomain ); 516 } 517 else 518 { 519 listener->DomainLost( service, ( DNSSDFlags ) flags, ifIndex, replyDomain ); 520 } 521 } 522 else 523 { 524 listener->EnumDomainsFailed( service, ( DNSSDError ) errorCode ); 525 } 526 } 527 528 exit: 529 530 return; 531 } 532 533 534 void DNSSD_API 535 CDNSSD::BrowseReply 536 ( 537 DNSServiceRef sdRef, 538 DNSServiceFlags flags, 539 uint32_t ifIndex, 540 DNSServiceErrorType errorCode, 541 const char *serviceNameUTF8, 542 const char *regTypeUTF8, 543 const char *replyDomainUTF8, 544 void *context 545 ) 546 { 547 CComObject<CDNSSDService> * service; 548 int err; 549 550 service = ( CComObject< CDNSSDService>* ) context; 551 require_action( service, exit, err = kDNSServiceErr_Unknown ); 552 553 if ( !service->Stopped() ) 554 { 555 IBrowseListener * listener; 556 557 listener = ( IBrowseListener* ) service->GetListener(); 558 require_action( listener, exit, err = kDNSServiceErr_Unknown ); 559 560 if ( !errorCode ) 561 { 562 CComBSTR serviceName; 563 CComBSTR regType; 564 CComBSTR replyDomain; 565 566 UTF8ToBSTR( serviceNameUTF8, serviceName ); 567 UTF8ToBSTR( regTypeUTF8, regType ); 568 UTF8ToBSTR( replyDomainUTF8, replyDomain ); 569 570 if ( flags & kDNSServiceFlagsAdd ) 571 { 572 listener->ServiceFound( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain ); 573 } 574 else 575 { 576 listener->ServiceLost( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain ); 577 } 578 } 579 else 580 { 581 listener->BrowseFailed( service, ( DNSSDError ) errorCode ); 582 } 583 } 584 585 exit: 586 587 return; 588 } 589 590 591 void DNSSD_API 592 CDNSSD::ResolveReply 593 ( 594 DNSServiceRef sdRef, 595 DNSServiceFlags flags, 596 uint32_t ifIndex, 597 DNSServiceErrorType errorCode, 598 const char *fullNameUTF8, 599 const char *hostNameUTF8, 600 uint16_t port, 601 uint16_t txtLen, 602 const unsigned char *txtRecord, 603 void *context 604 ) 605 { 606 CComObject<CDNSSDService> * service; 607 int err; 608 609 service = ( CComObject< CDNSSDService>* ) context; 610 require_action( service, exit, err = kDNSServiceErr_Unknown ); 611 612 if ( !service->Stopped() ) 613 { 614 IResolveListener * listener; 615 616 listener = ( IResolveListener* ) service->GetListener(); 617 require_action( listener, exit, err = kDNSServiceErr_Unknown ); 618 619 if ( !errorCode ) 620 { 621 CComBSTR fullName; 622 CComBSTR hostName; 623 CComBSTR regType; 624 CComBSTR replyDomain; 625 CComObject< CTXTRecord >* record; 626 BOOL ok; 627 628 ok = UTF8ToBSTR( fullNameUTF8, fullName ); 629 require_action( ok, exit, err = kDNSServiceErr_Unknown ); 630 ok = UTF8ToBSTR( hostNameUTF8, hostName ); 631 require_action( ok, exit, err = kDNSServiceErr_Unknown ); 632 633 try 634 { 635 record = new CComObject<CTXTRecord>(); 636 } 637 catch ( ... ) 638 { 639 record = NULL; 640 } 641 642 require_action( record, exit, err = kDNSServiceErr_NoMemory ); 643 record->AddRef(); 644 645 char buf[ 64 ]; 646 sprintf( buf, "txtLen = %d", txtLen ); 647 OutputDebugStringA( buf ); 648 649 if ( txtLen > 0 ) 650 { 651 record->SetBytes( txtRecord, txtLen ); 652 } 653 654 listener->ServiceResolved( service, ( DNSSDFlags ) flags, ifIndex, fullName, hostName, port, record ); 655 } 656 else 657 { 658 listener->ResolveFailed( service, ( DNSSDError ) errorCode ); 659 } 660 } 661 662 exit: 663 664 return; 665 } 666 667 668 void DNSSD_API 669 CDNSSD::RegisterReply 670 ( 671 DNSServiceRef sdRef, 672 DNSServiceFlags flags, 673 DNSServiceErrorType errorCode, 674 const char *serviceNameUTF8, 675 const char *regTypeUTF8, 676 const char *domainUTF8, 677 void *context 678 ) 679 { 680 CComObject<CDNSSDService> * service; 681 int err; 682 683 service = ( CComObject< CDNSSDService>* ) context; 684 require_action( service, exit, err = kDNSServiceErr_Unknown ); 685 686 if ( !service->Stopped() ) 687 { 688 IRegisterListener * listener; 689 690 listener = ( IRegisterListener* ) service->GetListener(); 691 require_action( listener, exit, err = kDNSServiceErr_Unknown ); 692 693 if ( !errorCode ) 694 { 695 CComBSTR serviceName; 696 CComBSTR regType; 697 CComBSTR domain; 698 BOOL ok; 699 700 ok = UTF8ToBSTR( serviceNameUTF8, serviceName ); 701 require_action( ok, exit, err = kDNSServiceErr_Unknown ); 702 ok = UTF8ToBSTR( regTypeUTF8, regType ); 703 require_action( ok, exit, err = kDNSServiceErr_Unknown ); 704 ok = UTF8ToBSTR( domainUTF8, domain ); 705 require_action( ok, exit, err = kDNSServiceErr_Unknown ); 706 707 listener->ServiceRegistered( service, ( DNSSDFlags ) flags, serviceName, regType, domain ); 708 } 709 else 710 { 711 listener->ServiceRegisterFailed( service, ( DNSSDError ) errorCode ); 712 } 713 } 714 715 exit: 716 717 return; 718 } 719 720 721 void DNSSD_API 722 CDNSSD::QueryRecordReply 723 ( 724 DNSServiceRef sdRef, 725 DNSServiceFlags flags, 726 uint32_t ifIndex, 727 DNSServiceErrorType errorCode, 728 const char *fullNameUTF8, 729 uint16_t rrtype, 730 uint16_t rrclass, 731 uint16_t rdlen, 732 const void *rdata, 733 uint32_t ttl, 734 void *context 735 ) 736 { 737 CComObject<CDNSSDService> * service; 738 int err; 739 740 service = ( CComObject< CDNSSDService>* ) context; 741 require_action( service, exit, err = kDNSServiceErr_Unknown ); 742 743 if ( !service->Stopped() ) 744 { 745 IQueryRecordListener * listener; 746 747 listener = ( IQueryRecordListener* ) service->GetListener(); 748 require_action( listener, exit, err = kDNSServiceErr_Unknown ); 749 750 if ( !errorCode ) 751 { 752 CComBSTR fullName; 753 VARIANT var; 754 BOOL ok; 755 756 ok = UTF8ToBSTR( fullNameUTF8, fullName ); 757 require_action( ok, exit, err = kDNSServiceErr_Unknown ); 758 ok = ByteArrayToVariant( rdata, rdlen, &var ); 759 require_action( ok, exit, err = kDNSServiceErr_Unknown ); 760 761 listener->QueryRecordAnswered( service, ( DNSSDFlags ) flags, ifIndex, fullName, ( DNSSDRRType ) rrtype, ( DNSSDRRClass ) rrclass, var, ttl ); 762 } 763 else 764 { 765 listener->QueryRecordFailed( service, ( DNSSDError ) errorCode ); 766 } 767 } 768 769 exit: 770 771 return; 772 } 773 774 775 void DNSSD_API 776 CDNSSD::GetAddrInfoReply 777 ( 778 DNSServiceRef sdRef, 779 DNSServiceFlags flags, 780 uint32_t ifIndex, 781 DNSServiceErrorType errorCode, 782 const char *hostNameUTF8, 783 const struct sockaddr *rawAddress, 784 uint32_t ttl, 785 void *context 786 ) 787 { 788 CComObject<CDNSSDService> * service; 789 int err; 790 791 service = ( CComObject< CDNSSDService>* ) context; 792 require_action( service, exit, err = kDNSServiceErr_Unknown ); 793 794 if ( !service->Stopped() ) 795 { 796 IGetAddrInfoListener * listener; 797 798 listener = ( IGetAddrInfoListener* ) service->GetListener(); 799 require_action( listener, exit, err = kDNSServiceErr_Unknown ); 800 801 if ( !errorCode ) 802 { 803 CComBSTR hostName; 804 DWORD sockaddrLen; 805 DNSSDAddressFamily addressFamily; 806 char addressUTF8[INET6_ADDRSTRLEN]; 807 DWORD addressLen = sizeof( addressUTF8 ); 808 CComBSTR address; 809 BOOL ok; 810 811 ok = UTF8ToBSTR( hostNameUTF8, hostName ); 812 require_action( ok, exit, err = kDNSServiceErr_Unknown ); 813 814 switch ( rawAddress->sa_family ) 815 { 816 case AF_INET: 817 { 818 addressFamily = kDNSSDAddressFamily_IPv4; 819 sockaddrLen = sizeof( sockaddr_in ); 820 } 821 break; 822 823 case AF_INET6: 824 { 825 addressFamily = kDNSSDAddressFamily_IPv6; 826 sockaddrLen = sizeof( sockaddr_in6 ); 827 } 828 break; 829 } 830 831 err = WSAAddressToStringA( ( LPSOCKADDR ) rawAddress, sockaddrLen, NULL, addressUTF8, &addressLen ); 832 require_noerr( err, exit ); 833 ok = UTF8ToBSTR( addressUTF8, address ); 834 require_action( ok, exit, err = kDNSServiceErr_Unknown ); 835 836 listener->GetAddrInfoReply( service, ( DNSSDFlags ) flags, ifIndex, hostName, addressFamily, address, ttl ); 837 } 838 else 839 { 840 listener->GetAddrInfoFailed( service, ( DNSSDError ) errorCode ); 841 } 842 } 843 844 exit: 845 846 return; 847 } 848 849 850 void DNSSD_API 851 CDNSSD::NATPortMappingReply 852 ( 853 DNSServiceRef sdRef, 854 DNSServiceFlags flags, 855 uint32_t ifIndex, 856 DNSServiceErrorType errorCode, 857 uint32_t externalAddress, /* four byte IPv4 address in network byte order */ 858 DNSServiceProtocol protocol, 859 uint16_t internalPort, 860 uint16_t externalPort, /* may be different than the requested port */ 861 uint32_t ttl, /* may be different than the requested ttl */ 862 void *context 863 ) 864 { 865 CComObject<CDNSSDService> * service; 866 int err; 867 868 service = ( CComObject< CDNSSDService>* ) context; 869 require_action( service, exit, err = kDNSServiceErr_Unknown ); 870 871 if ( !service->Stopped() ) 872 { 873 INATPortMappingListener * listener; 874 875 listener = ( INATPortMappingListener* ) service->GetListener(); 876 require_action( listener, exit, err = kDNSServiceErr_Unknown ); 877 878 if ( !errorCode ) 879 { 880 listener->MappingCreated( service, ( DNSSDFlags ) flags, ifIndex, externalAddress, ( DNSSDAddressFamily ) ( protocol & 0x8 ), ( DNSSDProtocol ) ( protocol & 0x80 ), internalPort, externalPort, ttl ); 881 } 882 else 883 { 884 listener->MappingFailed( service, ( DNSSDError ) errorCode ); 885 } 886 } 887 888 exit: 889 890 return; 891 } 892 893