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
15STDMETHODIMP 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
59exit:
60
61	if ( err && object )
62	{
63		object->Release();
64	}
65
66	return err;
67}
68
69
70STDMETHODIMP 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
117exit:
118
119	if ( err && object )
120	{
121		object->Release();
122	}
123
124	return err;
125}
126
127
128STDMETHODIMP 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
163exit:
164
165	if ( err && object )
166	{
167		object->Release();
168	}
169
170	return err;
171}
172
173
174STDMETHODIMP 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
236exit:
237
238	if ( err && object )
239	{
240		object->Release();
241	}
242
243	return err;
244}
245
246
247STDMETHODIMP 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
288exit:
289
290	if ( err && object )
291	{
292		object->Release();
293	}
294
295	return err;
296}
297
298
299STDMETHODIMP 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
340exit:
341
342	if ( err && object )
343	{
344		object->Release();
345	}
346
347	return err;
348}
349
350
351STDMETHODIMP 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
382exit:
383
384	if ( err && object )
385	{
386		object->Release();
387	}
388
389	return err;
390}
391
392
393STDMETHODIMP 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
431exit:
432
433	if ( err && object )
434	{
435		object->Release();
436	}
437
438	return err;
439}
440
441
442STDMETHODIMP 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
471exit:
472
473	if ( psa )
474	{
475		SafeArrayUnaccessData( psa );
476		psa = NULL;
477	}
478
479	return err;
480}
481
482
483void DNSSD_API
484CDNSSD::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
528exit:
529
530	return;
531}
532
533
534void DNSSD_API
535CDNSSD::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
585exit:
586
587	return;
588}
589
590
591void DNSSD_API
592CDNSSD::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
662exit:
663
664	return;
665}
666
667
668void DNSSD_API
669CDNSSD::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
715exit:
716
717	return;
718}
719
720
721void DNSSD_API
722CDNSSD::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
769exit:
770
771	return;
772}
773
774
775void DNSSD_API
776CDNSSD::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
844exit:
845
846	return;
847}
848
849
850void DNSSD_API
851CDNSSD::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
888exit:
889
890	return;
891}
892
893