1 // DNSSD.cpp : Implementation of CDNSSD
5 #include "DNSSDService.h"
8 #include <CommonServices.h>
9 #include <DebugServices.h>
10 #include "StringServices.h"
15 STDMETHODIMP
CDNSSD::Browse(DNSSDFlags flags
, ULONG ifIndex
, BSTR regtype
, BSTR domain
, IBrowseListener
* listener
, IDNSSDService
** browser
)
17 CComObject
<CDNSSDService
> * object
= NULL
;
18 std::string regtypeUTF8
;
19 std::string domainUTF8
;
20 DNSServiceRef sref
= NULL
;
21 DNSServiceErrorType err
= 0;
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
);
36 object
= new CComObject
<CDNSSDService
>();
43 require_action( object
!= NULL
, exit
, err
= kDNSServiceErr_NoMemory
);
44 hr
= object
->FinalConstruct();
45 require_action( hr
== S_OK
, exit
, err
= kDNSServiceErr_Unknown
);
48 err
= DNSServiceBrowse( &sref
, flags
, ifIndex
, regtypeUTF8
.c_str(), domainUTF8
.c_str(), ( DNSServiceBrowseReply
) &BrowseReply
, object
);
49 require_noerr( err
, exit
);
51 object
->SetServiceRef( sref
);
52 object
->SetListener( listener
);
55 require_noerr( err
, exit
);
70 STDMETHODIMP
CDNSSD::Resolve(DNSSDFlags flags
, ULONG ifIndex
, BSTR serviceName
, BSTR regType
, BSTR domain
, IResolveListener
* listener
, IDNSSDService
** service
)
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;
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
);
94 object
= new CComObject
<CDNSSDService
>();
101 require_action( object
!= NULL
, exit
, err
= kDNSServiceErr_NoMemory
);
102 hr
= object
->FinalConstruct();
103 require_action( hr
== S_OK
, exit
, err
= kDNSServiceErr_Unknown
);
106 err
= DNSServiceResolve( &sref
, flags
, ifIndex
, serviceNameUTF8
.c_str(), regTypeUTF8
.c_str(), domainUTF8
.c_str(), ( DNSServiceResolveReply
) &ResolveReply
, object
);
107 require_noerr( err
, exit
);
109 object
->SetServiceRef( sref
);
110 object
->SetListener( listener
);
113 require_noerr( err
, exit
);
128 STDMETHODIMP
CDNSSD::EnumerateDomains(DNSSDFlags flags
, ULONG ifIndex
, IDomainListener
*listener
, IDNSSDService
**service
)
130 CComObject
<CDNSSDService
> * object
= NULL
;
131 DNSServiceRef sref
= NULL
;
132 DNSServiceErrorType err
= 0;
140 object
= new CComObject
<CDNSSDService
>();
147 require_action( object
!= NULL
, exit
, err
= kDNSServiceErr_NoMemory
);
148 hr
= object
->FinalConstruct();
149 require_action( hr
== S_OK
, exit
, err
= kDNSServiceErr_Unknown
);
152 err
= DNSServiceEnumerateDomains( &sref
, flags
, ifIndex
, ( DNSServiceDomainEnumReply
) &DomainEnumReply
, object
);
153 require_noerr( err
, exit
);
155 object
->SetServiceRef( sref
);
156 object
->SetListener( listener
);
159 require_noerr( err
, exit
);
174 STDMETHODIMP
CDNSSD::Register(DNSSDFlags flags
, ULONG ifIndex
, BSTR serviceName
, BSTR regType
, BSTR domain
, BSTR host
, USHORT port
, ITXTRecord
*record
, IRegisterListener
*listener
, IDNSSDService
**service
)
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
;
183 DNSServiceRef sref
= NULL
;
184 DNSServiceErrorType err
= 0;
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
);
203 object
= new CComObject
<CDNSSDService
>();
210 require_action( object
!= NULL
, exit
, err
= kDNSServiceErr_NoMemory
);
211 hr
= object
->FinalConstruct();
212 require_action( hr
== S_OK
, exit
, err
= kDNSServiceErr_Unknown
);
217 CComObject
< CTXTRecord
> * realTXTRecord
;
219 realTXTRecord
= ( CComObject
< CTXTRecord
>* ) record
;
221 txtRecord
= realTXTRecord
->GetBytes();
222 txtLen
= realTXTRecord
->GetLen();
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
);
228 object
->SetServiceRef( sref
);
229 object
->SetListener( listener
);
232 require_noerr( err
, exit
);
247 STDMETHODIMP
CDNSSD::QueryRecord(DNSSDFlags flags
, ULONG ifIndex
, BSTR fullname
, DNSSDRRType rrtype
, DNSSDRRClass rrclass
, IQueryRecordListener
*listener
, IDNSSDService
**service
)
249 CComObject
<CDNSSDService
> * object
= NULL
;
250 DNSServiceRef sref
= NULL
;
251 std::string fullNameUTF8
;
252 DNSServiceErrorType err
= 0;
259 // Convert BSTR params to utf8
260 ok
= BSTRToUTF8( fullname
, fullNameUTF8
);
261 require_action( ok
, exit
, err
= kDNSServiceErr_BadParam
);
265 object
= new CComObject
<CDNSSDService
>();
272 require_action( object
!= NULL
, exit
, err
= kDNSServiceErr_NoMemory
);
273 hr
= object
->FinalConstruct();
274 require_action( hr
== S_OK
, exit
, err
= kDNSServiceErr_Unknown
);
277 err
= DNSServiceQueryRecord( &sref
, flags
, ifIndex
, fullNameUTF8
.c_str(), ( uint16_t ) rrtype
, ( uint16_t ) rrclass
, ( DNSServiceQueryRecordReply
) &QueryRecordReply
, object
);
278 require_noerr( err
, exit
);
280 object
->SetServiceRef( sref
);
281 object
->SetListener( listener
);
284 require_noerr( err
, exit
);
299 STDMETHODIMP
CDNSSD::GetAddrInfo(DNSSDFlags flags
, ULONG ifIndex
, DNSSDAddressFamily addressFamily
, BSTR hostName
, IGetAddrInfoListener
*listener
, IDNSSDService
**service
)
301 CComObject
<CDNSSDService
> * object
= NULL
;
302 DNSServiceRef sref
= NULL
;
303 std::string hostNameUTF8
;
304 DNSServiceErrorType err
= 0;
311 // Convert BSTR params to utf8
312 ok
= BSTRToUTF8( hostName
, hostNameUTF8
);
313 require_action( ok
, exit
, err
= kDNSServiceErr_BadParam
);
317 object
= new CComObject
<CDNSSDService
>();
324 require_action( object
!= NULL
, exit
, err
= kDNSServiceErr_NoMemory
);
325 hr
= object
->FinalConstruct();
326 require_action( hr
== S_OK
, exit
, err
= kDNSServiceErr_Unknown
);
329 err
= DNSServiceGetAddrInfo( &sref
, flags
, ifIndex
, addressFamily
, hostNameUTF8
.c_str(), ( DNSServiceGetAddrInfoReply
) &GetAddrInfoReply
, object
);
330 require_noerr( err
, exit
);
332 object
->SetServiceRef( sref
);
333 object
->SetListener( listener
);
336 require_noerr( err
, exit
);
351 STDMETHODIMP
CDNSSD::CreateConnection(IDNSSDService
**service
)
353 CComObject
<CDNSSDService
> * object
= NULL
;
354 DNSServiceRef sref
= NULL
;
355 DNSServiceErrorType err
= 0;
363 object
= new CComObject
<CDNSSDService
>();
370 require_action( object
!= NULL
, exit
, err
= kDNSServiceErr_NoMemory
);
371 hr
= object
->FinalConstruct();
372 require_action( hr
== S_OK
, exit
, err
= kDNSServiceErr_Unknown
);
375 err
= DNSServiceCreateConnection( &sref
);
376 require_noerr( err
, exit
);
378 object
->SetServiceRef( sref
);
393 STDMETHODIMP
CDNSSD::NATPortMappingCreate(DNSSDFlags flags
, ULONG ifIndex
, DNSSDAddressFamily addressFamily
, DNSSDProtocol protocol
, USHORT internalPort
, USHORT externalPort
, ULONG ttl
, INATPortMappingListener
*listener
, IDNSSDService
**service
)
395 CComObject
<CDNSSDService
> * object
= NULL
;
396 DNSServiceRef sref
= NULL
;
397 DNSServiceProtocol prot
= 0;
398 DNSServiceErrorType err
= 0;
406 object
= new CComObject
<CDNSSDService
>();
413 require_action( object
!= NULL
, exit
, err
= kDNSServiceErr_NoMemory
);
414 hr
= object
->FinalConstruct();
415 require_action( hr
== S_OK
, exit
, err
= kDNSServiceErr_Unknown
);
418 prot
= ( addressFamily
| protocol
);
420 err
= DNSServiceNATPortMappingCreate( &sref
, flags
, ifIndex
, prot
, internalPort
, externalPort
, ttl
, ( DNSServiceNATPortMappingReply
) &NATPortMappingReply
, object
);
421 require_noerr( err
, exit
);
423 object
->SetServiceRef( sref
);
424 object
->SetListener( listener
);
427 require_noerr( err
, exit
);
442 STDMETHODIMP
CDNSSD::GetProperty(BSTR prop
, VARIANT
* value
)
444 std::string propUTF8
;
445 std::vector
< BYTE
> byteArray
;
446 SAFEARRAY
* psa
= NULL
;
449 DNSServiceErrorType err
= 0;
452 // Convert BSTR params to utf8
453 ok
= BSTRToUTF8( prop
, propUTF8
);
454 require_action( ok
, exit
, err
= kDNSServiceErr_BadParam
);
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();
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
);
475 SafeArrayUnaccessData( psa
);
484 CDNSSD::DomainEnumReply
487 DNSServiceFlags flags
,
489 DNSServiceErrorType errorCode
,
490 const char *replyDomainUTF8
,
494 CComObject
<CDNSSDService
> * service
;
497 service
= ( CComObject
< CDNSSDService
>* ) context
;
498 require_action( service
, exit
, err
= kDNSServiceErr_Unknown
);
500 if ( !service
->Stopped() )
502 IDomainListener
* listener
;
504 listener
= ( IDomainListener
* ) service
->GetListener();
505 require_action( listener
, exit
, err
= kDNSServiceErr_Unknown
);
509 CComBSTR replyDomain
;
511 UTF8ToBSTR( replyDomainUTF8
, replyDomain
);
513 if ( flags
& kDNSServiceFlagsAdd
)
515 listener
->DomainFound( service
, ( DNSSDFlags
) flags
, ifIndex
, replyDomain
);
519 listener
->DomainLost( service
, ( DNSSDFlags
) flags
, ifIndex
, replyDomain
);
524 listener
->EnumDomainsFailed( service
, ( DNSSDError
) errorCode
);
538 DNSServiceFlags flags
,
540 DNSServiceErrorType errorCode
,
541 const char *serviceNameUTF8
,
542 const char *regTypeUTF8
,
543 const char *replyDomainUTF8
,
547 CComObject
<CDNSSDService
> * service
;
550 service
= ( CComObject
< CDNSSDService
>* ) context
;
551 require_action( service
, exit
, err
= kDNSServiceErr_Unknown
);
553 if ( !service
->Stopped() )
555 IBrowseListener
* listener
;
557 listener
= ( IBrowseListener
* ) service
->GetListener();
558 require_action( listener
, exit
, err
= kDNSServiceErr_Unknown
);
562 CComBSTR serviceName
;
564 CComBSTR replyDomain
;
566 UTF8ToBSTR( serviceNameUTF8
, serviceName
);
567 UTF8ToBSTR( regTypeUTF8
, regType
);
568 UTF8ToBSTR( replyDomainUTF8
, replyDomain
);
570 if ( flags
& kDNSServiceFlagsAdd
)
572 listener
->ServiceFound( service
, ( DNSSDFlags
) flags
, ifIndex
, serviceName
, regType
, replyDomain
);
576 listener
->ServiceLost( service
, ( DNSSDFlags
) flags
, ifIndex
, serviceName
, regType
, replyDomain
);
581 listener
->BrowseFailed( service
, ( DNSSDError
) errorCode
);
595 DNSServiceFlags flags
,
597 DNSServiceErrorType errorCode
,
598 const char *fullNameUTF8
,
599 const char *hostNameUTF8
,
602 const unsigned char *txtRecord
,
606 CComObject
<CDNSSDService
> * service
;
609 service
= ( CComObject
< CDNSSDService
>* ) context
;
610 require_action( service
, exit
, err
= kDNSServiceErr_Unknown
);
612 if ( !service
->Stopped() )
614 IResolveListener
* listener
;
616 listener
= ( IResolveListener
* ) service
->GetListener();
617 require_action( listener
, exit
, err
= kDNSServiceErr_Unknown
);
624 CComBSTR replyDomain
;
625 CComObject
< CTXTRecord
>* record
;
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
);
635 record
= new CComObject
<CTXTRecord
>();
642 require_action( record
, exit
, err
= kDNSServiceErr_NoMemory
);
646 sprintf( buf
, "txtLen = %d", txtLen
);
647 OutputDebugStringA( buf
);
651 record
->SetBytes( txtRecord
, txtLen
);
654 listener
->ServiceResolved( service
, ( DNSSDFlags
) flags
, ifIndex
, fullName
, hostName
, port
, record
);
658 listener
->ResolveFailed( service
, ( DNSSDError
) errorCode
);
669 CDNSSD::RegisterReply
672 DNSServiceFlags flags
,
673 DNSServiceErrorType errorCode
,
674 const char *serviceNameUTF8
,
675 const char *regTypeUTF8
,
676 const char *domainUTF8
,
680 CComObject
<CDNSSDService
> * service
;
683 service
= ( CComObject
< CDNSSDService
>* ) context
;
684 require_action( service
, exit
, err
= kDNSServiceErr_Unknown
);
686 if ( !service
->Stopped() )
688 IRegisterListener
* listener
;
690 listener
= ( IRegisterListener
* ) service
->GetListener();
691 require_action( listener
, exit
, err
= kDNSServiceErr_Unknown
);
695 CComBSTR serviceName
;
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
);
707 listener
->ServiceRegistered( service
, ( DNSSDFlags
) flags
, serviceName
, regType
, domain
);
711 listener
->ServiceRegisterFailed( service
, ( DNSSDError
) errorCode
);
722 CDNSSD::QueryRecordReply
725 DNSServiceFlags flags
,
727 DNSServiceErrorType errorCode
,
728 const char *fullNameUTF8
,
737 CComObject
<CDNSSDService
> * service
;
740 service
= ( CComObject
< CDNSSDService
>* ) context
;
741 require_action( service
, exit
, err
= kDNSServiceErr_Unknown
);
743 if ( !service
->Stopped() )
745 IQueryRecordListener
* listener
;
747 listener
= ( IQueryRecordListener
* ) service
->GetListener();
748 require_action( listener
, exit
, err
= kDNSServiceErr_Unknown
);
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
);
761 listener
->QueryRecordAnswered( service
, ( DNSSDFlags
) flags
, ifIndex
, fullName
, ( DNSSDRRType
) rrtype
, ( DNSSDRRClass
) rrclass
, var
, ttl
);
765 listener
->QueryRecordFailed( service
, ( DNSSDError
) errorCode
);
776 CDNSSD::GetAddrInfoReply
779 DNSServiceFlags flags
,
781 DNSServiceErrorType errorCode
,
782 const char *hostNameUTF8
,
783 const struct sockaddr
*rawAddress
,
788 CComObject
<CDNSSDService
> * service
;
791 service
= ( CComObject
< CDNSSDService
>* ) context
;
792 require_action( service
, exit
, err
= kDNSServiceErr_Unknown
);
794 if ( !service
->Stopped() )
796 IGetAddrInfoListener
* listener
;
798 listener
= ( IGetAddrInfoListener
* ) service
->GetListener();
799 require_action( listener
, exit
, err
= kDNSServiceErr_Unknown
);
805 DNSSDAddressFamily addressFamily
;
806 char addressUTF8
[INET6_ADDRSTRLEN
];
807 DWORD addressLen
= sizeof( addressUTF8
);
811 ok
= UTF8ToBSTR( hostNameUTF8
, hostName
);
812 require_action( ok
, exit
, err
= kDNSServiceErr_Unknown
);
814 switch ( rawAddress
->sa_family
)
818 addressFamily
= kDNSSDAddressFamily_IPv4
;
819 sockaddrLen
= sizeof( sockaddr_in
);
825 addressFamily
= kDNSSDAddressFamily_IPv6
;
826 sockaddrLen
= sizeof( sockaddr_in6
);
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
);
836 listener
->GetAddrInfoReply( service
, ( DNSSDFlags
) flags
, ifIndex
, hostName
, addressFamily
, address
, ttl
);
840 listener
->GetAddrInfoFailed( service
, ( DNSSDError
) errorCode
);
851 CDNSSD::NATPortMappingReply
854 DNSServiceFlags flags
,
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 */
865 CComObject
<CDNSSDService
> * service
;
868 service
= ( CComObject
< CDNSSDService
>* ) context
;
869 require_action( service
, exit
, err
= kDNSServiceErr_Unknown
);
871 if ( !service
->Stopped() )
873 INATPortMappingListener
* listener
;
875 listener
= ( INATPortMappingListener
* ) service
->GetListener();
876 require_action( listener
, exit
, err
= kDNSServiceErr_Unknown
);
880 listener
->MappingCreated( service
, ( DNSSDFlags
) flags
, ifIndex
, externalAddress
, ( DNSSDAddressFamily
) ( protocol
& 0x8 ), ( DNSSDProtocol
) ( protocol
& 0x80 ), internalPort
, externalPort
, ttl
);
884 listener
->MappingFailed( service
, ( DNSSDError
) errorCode
);