]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSWindows/DLLX/DNSSDService.cpp
219c6100cef2cc8a3a04a87e1644ad8ad3b56a5f
[apple/mdnsresponder.git] / mDNSWindows / DLLX / DNSSDService.cpp
1 /* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2009 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 Change History (most recent first):
18
19 $Log: DNSSDService.cpp,v $
20 Revision 1.1 2009/05/26 04:43:54 herscher
21 <rdar://problem/3948252> COM component that can be used with any .NET language and VB.
22
23
24 */
25
26 #pragma warning(disable:4995)
27
28 #include "stdafx.h"
29 #include <strsafe.h>
30 #include "DNSSDService.h"
31 #include "DNSSDEventManager.h"
32 #include "DNSSDRecord.h"
33 #include "TXTRecord.h"
34 #include "StringServices.h"
35 #include <DebugServices.h>
36
37
38 #define WM_SOCKET (WM_APP + 100)
39
40
41 // CDNSSDService
42
43 BOOL CDNSSDService::m_registeredWindowClass = FALSE;
44 HWND CDNSSDService::m_hiddenWindow = NULL;
45 CDNSSDService::SocketMap CDNSSDService::m_socketMap;
46
47
48 HRESULT CDNSSDService::FinalConstruct()
49 {
50 DNSServiceErrorType err = 0;
51 HRESULT hr = S_OK;
52
53 m_isPrimary = TRUE;
54 err = DNSServiceCreateConnection( &m_primary );
55 require_action( !err, exit, hr = E_FAIL );
56
57 if ( !m_hiddenWindow )
58 {
59 TCHAR windowClassName[ 256 ];
60
61 StringCchPrintf( windowClassName, sizeof( windowClassName ) / sizeof( TCHAR ), TEXT( "Bonjour Hidden Window %d" ), GetProcessId( NULL ) );
62
63 if ( !m_registeredWindowClass )
64 {
65 WNDCLASS wc;
66 ATOM atom;
67
68 wc.style = 0;
69 wc.lpfnWndProc = WndProc;
70 wc.cbClsExtra = 0;
71 wc.cbWndExtra = 0;
72 wc.hInstance = NULL;
73 wc.hIcon = NULL;
74 wc.hCursor = NULL;
75 wc.hbrBackground = NULL;
76 wc.lpszMenuName = NULL;
77 wc.lpszClassName = windowClassName;
78
79 atom = RegisterClass(&wc);
80 require_action( atom != NULL, exit, hr = E_FAIL );
81
82 m_registeredWindowClass = TRUE;
83 }
84
85 m_hiddenWindow = CreateWindow( windowClassName, windowClassName, WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL, GetModuleHandle( NULL ), NULL );
86 require_action( m_hiddenWindow != NULL, exit, hr = E_FAIL );
87 }
88
89 err = WSAAsyncSelect( DNSServiceRefSockFD( m_primary ), m_hiddenWindow, WM_SOCKET, FD_READ );
90 require_action( !err, exit, hr = E_FAIL );
91
92 m_socketMap[ DNSServiceRefSockFD( m_primary ) ] = this;
93
94 exit:
95
96 return hr;
97 }
98
99
100 void CDNSSDService::FinalRelease()
101 {
102 dlog( kDebugLevelTrace, "FinalRelease()\n" );
103 Stop();
104 }
105
106
107 STDMETHODIMP CDNSSDService::EnumerateDomains(DNSSDFlags flags, ULONG ifIndex, IDNSSDEventManager *eventManager, IDNSSDService **service)
108 {
109 CComObject<CDNSSDService> * object = NULL;
110 DNSServiceRef subord = NULL;
111 DNSServiceErrorType err = 0;
112 HRESULT hr = 0;
113
114 check( m_primary );
115
116 // Initialize
117 *service = NULL;
118
119 try
120 {
121 object = new CComObject<CDNSSDService>();
122 }
123 catch ( ... )
124 {
125 object = NULL;
126 }
127
128 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
129 object->AddRef();
130
131 subord = m_primary;
132 err = DNSServiceEnumerateDomains( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, ( DNSServiceDomainEnumReply ) &DomainEnumReply, object );
133 require_noerr( err, exit );
134
135 object->SetPrimaryRef( m_primary );
136 object->SetSubordRef( subord );
137 object->SetEventManager( eventManager );
138
139 *service = object;
140
141 exit:
142
143 if ( err && object )
144 {
145 object->Release();
146 }
147
148 return err;
149 }
150
151
152 STDMETHODIMP CDNSSDService::Browse(DNSSDFlags flags, ULONG ifIndex, BSTR regtype, BSTR domain, IDNSSDEventManager* eventManager, IDNSSDService** service )
153 {
154 CComObject<CDNSSDService> * object = NULL;
155 std::string regtypeUTF8;
156 std::string domainUTF8;
157 DNSServiceRef subord = NULL;
158 DNSServiceErrorType err = 0;
159 HRESULT hr = 0;
160 BOOL ok;
161
162 check( m_primary );
163
164 // Initialize
165 *service = NULL;
166
167 // Convert BSTR params to utf8
168 ok = BSTRToUTF8( regtype, regtypeUTF8 );
169 require_action( ok, exit, err = kDNSServiceErr_BadParam );
170 ok = BSTRToUTF8( domain, domainUTF8 );
171 require_action( ok, exit, err = kDNSServiceErr_BadParam );
172
173 try
174 {
175 object = new CComObject<CDNSSDService>();
176 }
177 catch ( ... )
178 {
179 object = NULL;
180 }
181
182 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
183 object->AddRef();
184
185 subord = m_primary;
186 err = DNSServiceBrowse( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, regtypeUTF8.c_str(), ( domainUTF8.size() > 0 ) ? domainUTF8.c_str() : NULL, ( DNSServiceBrowseReply ) &BrowseReply, object );
187 require_noerr( err, exit );
188
189 object->SetPrimaryRef( m_primary );
190 object->SetSubordRef( subord );
191 object->SetEventManager( eventManager );
192
193 *service = object;
194
195 exit:
196
197 if ( err && object )
198 {
199 object->Release();
200 }
201
202 return err;
203 }
204
205
206 STDMETHODIMP CDNSSDService::Resolve(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, IDNSSDEventManager* eventManager, IDNSSDService** service)
207 {
208 CComObject<CDNSSDService> * object = NULL;
209 std::string serviceNameUTF8;
210 std::string regTypeUTF8;
211 std::string domainUTF8;
212 DNSServiceRef subord = NULL;
213 DNSServiceErrorType err = 0;
214 HRESULT hr = 0;
215 BOOL ok;
216
217 check( m_primary );
218
219 // Initialize
220 *service = NULL;
221
222 // Convert BSTR params to utf8
223 ok = BSTRToUTF8( serviceName, serviceNameUTF8 );
224 require_action( ok, exit, err = kDNSServiceErr_BadParam );
225 ok = BSTRToUTF8( regType, regTypeUTF8 );
226 require_action( ok, exit, err = kDNSServiceErr_BadParam );
227 ok = BSTRToUTF8( domain, domainUTF8 );
228 require_action( ok, exit, err = kDNSServiceErr_BadParam );
229
230 try
231 {
232 object = new CComObject<CDNSSDService>();
233 }
234 catch ( ... )
235 {
236 object = NULL;
237 }
238
239 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
240 object->AddRef();
241
242 subord = m_primary;
243 err = DNSServiceResolve( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, serviceNameUTF8.c_str(), regTypeUTF8.c_str(), domainUTF8.c_str(), ( DNSServiceResolveReply ) &ResolveReply, object );
244 require_noerr( err, exit );
245
246 object->SetPrimaryRef( m_primary );
247 object->SetSubordRef( subord );
248 object->SetEventManager( eventManager );
249
250 *service = object;
251
252 exit:
253
254 if ( err && object )
255 {
256 object->Release();
257 }
258
259 return err;
260 }
261
262
263 STDMETHODIMP CDNSSDService::Register(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, BSTR host, USHORT port, ITXTRecord *record, IDNSSDEventManager *eventManager, IDNSSDService **service)
264 {
265 CComObject<CDNSSDService> * object = NULL;
266 std::string serviceNameUTF8;
267 std::string regTypeUTF8;
268 std::string domainUTF8;
269 std::string hostUTF8;
270 const void * txtRecord = NULL;
271 uint16_t txtLen = 0;
272 DNSServiceRef subord = NULL;
273 DNSServiceErrorType err = 0;
274 HRESULT hr = 0;
275 BOOL ok;
276
277 check( m_primary );
278
279 // Initialize
280 *service = NULL;
281
282 // Convert BSTR params to utf8
283 ok = BSTRToUTF8( serviceName, serviceNameUTF8 );
284 require_action( ok, exit, err = kDNSServiceErr_BadParam );
285 ok = BSTRToUTF8( regType, regTypeUTF8 );
286 require_action( ok, exit, err = kDNSServiceErr_BadParam );
287 ok = BSTRToUTF8( domain, domainUTF8 );
288 require_action( ok, exit, err = kDNSServiceErr_BadParam );
289 ok = BSTRToUTF8( host, hostUTF8 );
290 require_action( ok, exit, err = kDNSServiceErr_BadParam );
291
292 try
293 {
294 object = new CComObject<CDNSSDService>();
295 }
296 catch ( ... )
297 {
298 object = NULL;
299 }
300
301 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
302 object->AddRef();
303
304 if ( record )
305 {
306 CComObject< CTXTRecord > * realTXTRecord;
307
308 realTXTRecord = ( CComObject< CTXTRecord >* ) record;
309
310 txtRecord = realTXTRecord->GetBytes();
311 txtLen = realTXTRecord->GetLen();
312 }
313
314 subord = m_primary;
315 err = DNSServiceRegister( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, serviceNameUTF8.c_str(), regTypeUTF8.c_str(), ( domainUTF8.size() > 0 ) ? domainUTF8.c_str() : NULL, hostUTF8.c_str(), htons( port ), txtLen, txtRecord, ( DNSServiceRegisterReply ) &RegisterReply, object );
316 require_noerr( err, exit );
317
318 object->SetPrimaryRef( m_primary );
319 object->SetSubordRef( subord );
320 object->SetEventManager( eventManager );
321
322 *service = object;
323
324 exit:
325
326 if ( err && object )
327 {
328 object->Release();
329 }
330
331 return err;
332 }
333
334
335 STDMETHODIMP CDNSSDService::QueryRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullname, DNSSDRRType rrtype, DNSSDRRClass rrclass, IDNSSDEventManager *eventManager, IDNSSDService **service)
336 {
337 CComObject<CDNSSDService> * object = NULL;
338 DNSServiceRef subord = NULL;
339 std::string fullNameUTF8;
340 DNSServiceErrorType err = 0;
341 HRESULT hr = 0;
342 BOOL ok;
343
344 check( m_primary );
345
346 // Initialize
347 *service = NULL;
348
349 // Convert BSTR params to utf8
350 ok = BSTRToUTF8( fullname, fullNameUTF8 );
351 require_action( ok, exit, err = kDNSServiceErr_BadParam );
352
353 try
354 {
355 object = new CComObject<CDNSSDService>();
356 }
357 catch ( ... )
358 {
359 object = NULL;
360 }
361
362 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
363 object->AddRef();
364
365 subord = m_primary;
366 err = DNSServiceQueryRecord( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, fullNameUTF8.c_str(), ( uint16_t ) rrtype, ( uint16_t ) rrclass, ( DNSServiceQueryRecordReply ) &QueryRecordReply, object );
367 require_noerr( err, exit );
368
369 object->SetPrimaryRef( m_primary );
370 object->SetSubordRef( subord );
371 object->SetEventManager( eventManager );
372
373 *service = object;
374
375 exit:
376
377 if ( err && object )
378 {
379 object->Release();
380 }
381
382 return err;
383 }
384
385
386 STDMETHODIMP CDNSSDService::RegisterRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullName, DNSSDRRType rrtype, DNSSDRRClass rrclass, VARIANT rdata, ULONG ttl, IDNSSDEventManager* eventManager, IDNSSDRecord** record)
387 {
388 CComObject<CDNSSDRecord> * object = NULL;
389 DNSRecordRef rref = NULL;
390 std::string fullNameUTF8;
391 std::vector< BYTE > byteArray;
392 const void * byteArrayPtr = NULL;
393 DNSServiceErrorType err = 0;
394 HRESULT hr = 0;
395 BOOL ok;
396
397 check( m_primary );
398
399 // Initialize
400 *object = NULL;
401
402 // Convert BSTR params to utf8
403 ok = BSTRToUTF8( fullName, fullNameUTF8 );
404 require_action( ok, exit, err = kDNSServiceErr_BadParam );
405
406 // Convert the VARIANT
407 ok = VariantToByteArray( &rdata, byteArray );
408 require_action( ok, exit, err = kDNSServiceErr_Unknown );
409
410 try
411 {
412 object = new CComObject<CDNSSDRecord>();
413 }
414 catch ( ... )
415 {
416 object = NULL;
417 }
418
419 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
420 object->AddRef();
421
422 err = DNSServiceRegisterRecord( m_primary, &rref, flags, ifIndex, fullNameUTF8.c_str(), rrtype, rrclass, ( uint16_t ) byteArray.size(), byteArray.size() > 0 ? &byteArray[ 0 ] : NULL, ttl, &RegisterRecordReply, object );
423 require_noerr( err, exit );
424
425 object->SetServiceObject( this );
426 object->SetRecordRef( rref );
427 this->SetEventManager( eventManager );
428
429 *record = object;
430
431 exit:
432
433 if ( err && object )
434 {
435 object->Release();
436 }
437
438 return err;
439 }
440
441
442 STDMETHODIMP CDNSSDService::AddRecord(DNSSDFlags flags, DNSSDRRType rrtype, VARIANT rdata, ULONG ttl, IDNSSDRecord ** record)
443 {
444 CComObject<CDNSSDRecord> * object = NULL;
445 DNSRecordRef rref = NULL;
446 std::vector< BYTE > byteArray;
447 const void * byteArrayPtr = NULL;
448 DNSServiceErrorType err = 0;
449 HRESULT hr = 0;
450 BOOL ok;
451
452 check( m_primary );
453
454 // Initialize
455 *object = NULL;
456
457 // Convert the VARIANT
458 ok = VariantToByteArray( &rdata, byteArray );
459 require_action( ok, exit, err = kDNSServiceErr_Unknown );
460
461 try
462 {
463 object = new CComObject<CDNSSDRecord>();
464 }
465 catch ( ... )
466 {
467 object = NULL;
468 }
469
470 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
471 object->AddRef();
472
473 err = DNSServiceAddRecord( m_primary, &rref, flags, rrtype, ( uint16_t ) byteArray.size(), byteArray.size() > 0 ? &byteArray[ 0 ] : NULL, ttl );
474 require_noerr( err, exit );
475
476 object->SetServiceObject( this );
477 object->SetRecordRef( rref );
478
479 *record = object;
480
481 exit:
482
483 if ( err && object )
484 {
485 object->Release();
486 }
487
488 return err;
489 }
490
491 STDMETHODIMP CDNSSDService::ReconfirmRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullName, DNSSDRRType rrtype, DNSSDRRClass rrclass, VARIANT rdata)
492 {
493 std::string fullNameUTF8;
494 std::vector< BYTE > byteArray;
495 const void * byteArrayPtr = NULL;
496 DNSServiceErrorType err = 0;
497 HRESULT hr = 0;
498 BOOL ok;
499
500 // Convert BSTR params to utf8
501 ok = BSTRToUTF8( fullName, fullNameUTF8 );
502 require_action( ok, exit, err = kDNSServiceErr_BadParam );
503
504 // Convert the VARIANT
505 ok = VariantToByteArray( &rdata, byteArray );
506 require_action( ok, exit, err = kDNSServiceErr_Unknown );
507
508 err = DNSServiceReconfirmRecord( flags, ifIndex, fullNameUTF8.c_str(), rrtype, rrclass, ( uint16_t ) byteArray.size(), byteArray.size() > 0 ? &byteArray[ 0 ] : NULL );
509 require_noerr( err, exit );
510
511 exit:
512
513 return err;
514 }
515
516
517 STDMETHODIMP CDNSSDService::GetProperty(BSTR prop, VARIANT * value )
518 {
519 std::string propUTF8;
520 std::vector< BYTE > byteArray;
521 SAFEARRAY * psa = NULL;
522 BYTE * pData = NULL;
523 uint32_t elems = 0;
524 DNSServiceErrorType err = 0;
525 BOOL ok = TRUE;
526
527 // Convert BSTR params to utf8
528 ok = BSTRToUTF8( prop, propUTF8 );
529 require_action( ok, exit, err = kDNSServiceErr_BadParam );
530
531 // Setup the byte array
532 require_action( V_VT( value ) == ( VT_ARRAY|VT_UI1 ), exit, err = kDNSServiceErr_Unknown );
533 psa = V_ARRAY( value );
534 require_action( psa, exit, err = kDNSServiceErr_Unknown );
535 require_action( SafeArrayGetDim( psa ) == 1, exit, err = kDNSServiceErr_Unknown );
536 byteArray.reserve( psa->rgsabound[0].cElements );
537 byteArray.assign( byteArray.capacity(), 0 );
538 elems = ( uint32_t ) byteArray.capacity();
539
540 // Call the function and package the return value in the Variant
541 err = DNSServiceGetProperty( propUTF8.c_str(), &byteArray[ 0 ], &elems );
542 require_noerr( err, exit );
543 ok = ByteArrayToVariant( &byteArray[ 0 ], elems, value );
544 require_action( ok, exit, err = kDNSSDError_Unknown );
545
546 exit:
547
548 if ( psa )
549 {
550 SafeArrayUnaccessData( psa );
551 psa = NULL;
552 }
553
554 return err;
555 }
556
557 STDMETHODIMP CDNSSDService::GetAddrInfo(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, BSTR hostName, IDNSSDEventManager *eventManager, IDNSSDService **service)
558 {
559 CComObject<CDNSSDService> * object = NULL;
560 DNSServiceRef subord = NULL;
561 std::string hostNameUTF8;
562 DNSServiceErrorType err = 0;
563 HRESULT hr = 0;
564 BOOL ok;
565
566 check( m_primary );
567
568 // Initialize
569 *service = NULL;
570
571 // Convert BSTR params to utf8
572 ok = BSTRToUTF8( hostName, hostNameUTF8 );
573 require_action( ok, exit, err = kDNSServiceErr_BadParam );
574
575 try
576 {
577 object = new CComObject<CDNSSDService>();
578 }
579 catch ( ... )
580 {
581 object = NULL;
582 }
583
584 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
585 object->AddRef();
586
587 subord = m_primary;
588 err = DNSServiceGetAddrInfo( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, addressFamily, hostNameUTF8.c_str(), ( DNSServiceGetAddrInfoReply ) &GetAddrInfoReply, object );
589 require_noerr( err, exit );
590
591 object->SetPrimaryRef( m_primary );
592 object->SetSubordRef( subord );
593 object->SetEventManager( eventManager );
594
595 *service = object;
596
597 exit:
598
599 if ( err && object )
600 {
601 object->Release();
602 }
603
604 return err;
605 }
606
607
608 STDMETHODIMP CDNSSDService::NATPortMappingCreate(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, DNSSDProtocol protocol, USHORT internalPort, USHORT externalPort, ULONG ttl, IDNSSDEventManager *eventManager, IDNSSDService **service)
609 {
610 CComObject<CDNSSDService> * object = NULL;
611 DNSServiceRef subord = NULL;
612 DNSServiceProtocol prot = 0;
613 DNSServiceErrorType err = 0;
614 HRESULT hr = 0;
615
616 check( m_primary );
617
618 // Initialize
619 *service = NULL;
620
621 try
622 {
623 object = new CComObject<CDNSSDService>();
624 }
625 catch ( ... )
626 {
627 object = NULL;
628 }
629
630 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
631 object->AddRef();
632
633 prot = ( addressFamily | protocol );
634
635 subord = m_primary;
636 err = DNSServiceNATPortMappingCreate( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, prot, htons( internalPort ), htons( externalPort ), ttl, ( DNSServiceNATPortMappingReply ) &NATPortMappingReply, object );
637 require_noerr( err, exit );
638
639 object->SetPrimaryRef( m_primary );
640 object->SetSubordRef( subord );
641 object->SetEventManager( eventManager );
642
643 *service = object;
644
645 exit:
646
647 if ( err && object )
648 {
649 object->Release();
650 }
651
652 return err;
653 }
654
655
656 STDMETHODIMP CDNSSDService::Stop(void)
657 {
658 if ( !m_stopped )
659 {
660 m_stopped = TRUE;
661
662 dlog( kDebugLevelTrace, "Stop()\n" );
663
664 if ( m_isPrimary && m_primary )
665 {
666 SocketMap::iterator it;
667
668 if ( m_hiddenWindow )
669 {
670 WSAAsyncSelect( DNSServiceRefSockFD( m_primary ), m_hiddenWindow, 0, 0 );
671 }
672
673 it = m_socketMap.find( DNSServiceRefSockFD( m_primary ) );
674
675 if ( it != m_socketMap.end() )
676 {
677 m_socketMap.erase( it );
678 }
679
680 DNSServiceRefDeallocate( m_primary );
681 m_primary = NULL;
682 }
683 else if ( m_subord )
684 {
685 DNSServiceRefDeallocate( m_subord );
686 m_subord = NULL;
687 }
688
689 if ( m_eventManager != NULL )
690 {
691 m_eventManager->Release();
692 m_eventManager = NULL;
693 }
694 }
695
696 return S_OK;
697 }
698
699
700 void DNSSD_API
701 CDNSSDService::DomainEnumReply
702 (
703 DNSServiceRef sdRef,
704 DNSServiceFlags flags,
705 uint32_t ifIndex,
706 DNSServiceErrorType errorCode,
707 const char *replyDomainUTF8,
708 void *context
709 )
710 {
711 CComObject<CDNSSDService> * service = NULL;
712 CDNSSDEventManager * eventManager = NULL;
713 int err = 0;
714
715 service = ( CComObject< CDNSSDService>* ) context;
716 require_action( service, exit, err = kDNSServiceErr_Unknown );
717
718 if ( service->ShouldHandleReply( errorCode, eventManager ) )
719 {
720 CComBSTR replyDomain;
721 BOOL ok;
722
723 ok = UTF8ToBSTR( replyDomainUTF8, replyDomain );
724 require_action( ok, exit, err = kDNSServiceErr_Unknown );
725
726 if ( flags & kDNSServiceFlagsAdd )
727 {
728 eventManager->Fire_DomainFound( service, ( DNSSDFlags ) flags, ifIndex, replyDomain );
729 }
730 else
731 {
732 eventManager->Fire_DomainLost( service, ( DNSSDFlags ) flags, ifIndex, replyDomain );
733 }
734 }
735
736 exit:
737
738 return;
739 }
740
741
742 void DNSSD_API
743 CDNSSDService::BrowseReply
744 (
745 DNSServiceRef sdRef,
746 DNSServiceFlags flags,
747 uint32_t ifIndex,
748 DNSServiceErrorType errorCode,
749 const char *serviceNameUTF8,
750 const char *regTypeUTF8,
751 const char *replyDomainUTF8,
752 void *context
753 )
754 {
755 CComObject<CDNSSDService> * service = NULL;
756 CDNSSDEventManager * eventManager = NULL;
757 int err = 0;
758
759 service = ( CComObject< CDNSSDService>* ) context;
760 require_action( service, exit, err = kDNSServiceErr_Unknown );
761
762 if ( service->ShouldHandleReply( errorCode, eventManager ) )
763 {
764 CComBSTR serviceName;
765 CComBSTR regType;
766 CComBSTR replyDomain;
767
768 UTF8ToBSTR( serviceNameUTF8, serviceName );
769 UTF8ToBSTR( regTypeUTF8, regType );
770 UTF8ToBSTR( replyDomainUTF8, replyDomain );
771
772 if ( flags & kDNSServiceFlagsAdd )
773 {
774 eventManager->Fire_ServiceFound( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain );
775 }
776 else
777 {
778 eventManager->Fire_ServiceLost( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain );
779 }
780 }
781
782 exit:
783
784 return;
785 }
786
787
788 void DNSSD_API
789 CDNSSDService::ResolveReply
790 (
791 DNSServiceRef sdRef,
792 DNSServiceFlags flags,
793 uint32_t ifIndex,
794 DNSServiceErrorType errorCode,
795 const char *fullNameUTF8,
796 const char *hostNameUTF8,
797 uint16_t port,
798 uint16_t txtLen,
799 const unsigned char *txtRecord,
800 void *context
801 )
802 {
803 CComObject<CDNSSDService> * service = NULL;
804 CDNSSDEventManager * eventManager = NULL;
805 int err = 0;
806
807 service = ( CComObject< CDNSSDService>* ) context;
808 require_action( service, exit, err = kDNSServiceErr_Unknown );
809
810 if ( service->ShouldHandleReply( errorCode, eventManager ) )
811 {
812 CComBSTR fullName;
813 CComBSTR hostName;
814 CComBSTR regType;
815 CComBSTR replyDomain;
816 CComObject< CTXTRecord >* record;
817 BOOL ok;
818
819 ok = UTF8ToBSTR( fullNameUTF8, fullName );
820 require_action( ok, exit, err = kDNSServiceErr_Unknown );
821 ok = UTF8ToBSTR( hostNameUTF8, hostName );
822 require_action( ok, exit, err = kDNSServiceErr_Unknown );
823
824 try
825 {
826 record = new CComObject<CTXTRecord>();
827 }
828 catch ( ... )
829 {
830 record = NULL;
831 }
832
833 require_action( record, exit, err = kDNSServiceErr_NoMemory );
834 record->AddRef();
835
836 if ( txtLen > 0 )
837 {
838 record->SetBytes( txtRecord, txtLen );
839 }
840
841 eventManager->Fire_ServiceResolved( service, ( DNSSDFlags ) flags, ifIndex, fullName, hostName, ntohs( port ), record );
842 }
843
844 exit:
845
846 return;
847 }
848
849
850 void DNSSD_API
851 CDNSSDService::RegisterReply
852 (
853 DNSServiceRef sdRef,
854 DNSServiceFlags flags,
855 DNSServiceErrorType errorCode,
856 const char *serviceNameUTF8,
857 const char *regTypeUTF8,
858 const char *domainUTF8,
859 void *context
860 )
861 {
862 CComObject<CDNSSDService> * service = NULL;
863 CDNSSDEventManager * eventManager = NULL;
864 int err = 0;
865
866 service = ( CComObject< CDNSSDService>* ) context;
867 require_action( service, exit, err = kDNSServiceErr_Unknown );
868
869 if ( service->ShouldHandleReply( errorCode, eventManager ) )
870 {
871 CComBSTR serviceName;
872 CComBSTR regType;
873 CComBSTR domain;
874 BOOL ok;
875
876 ok = UTF8ToBSTR( serviceNameUTF8, serviceName );
877 require_action( ok, exit, err = kDNSServiceErr_Unknown );
878 ok = UTF8ToBSTR( regTypeUTF8, regType );
879 require_action( ok, exit, err = kDNSServiceErr_Unknown );
880 ok = UTF8ToBSTR( domainUTF8, domain );
881 require_action( ok, exit, err = kDNSServiceErr_Unknown );
882
883 eventManager->Fire_ServiceRegistered( service, ( DNSSDFlags ) flags, serviceName, regType, domain );
884 }
885
886 exit:
887
888 return;
889 }
890
891
892 void DNSSD_API
893 CDNSSDService::QueryRecordReply
894 (
895 DNSServiceRef sdRef,
896 DNSServiceFlags flags,
897 uint32_t ifIndex,
898 DNSServiceErrorType errorCode,
899 const char *fullNameUTF8,
900 uint16_t rrtype,
901 uint16_t rrclass,
902 uint16_t rdlen,
903 const void *rdata,
904 uint32_t ttl,
905 void *context
906 )
907 {
908 CComObject<CDNSSDService> * service = NULL;
909 CDNSSDEventManager * eventManager = NULL;
910 int err = 0;
911
912 service = ( CComObject< CDNSSDService>* ) context;
913 require_action( service, exit, err = kDNSServiceErr_Unknown );
914
915 if ( service->ShouldHandleReply( errorCode, eventManager ) )
916 {
917 CComBSTR fullName;
918 VARIANT var;
919 BOOL ok;
920
921 ok = UTF8ToBSTR( fullNameUTF8, fullName );
922 require_action( ok, exit, err = kDNSServiceErr_Unknown );
923 ok = ByteArrayToVariant( rdata, rdlen, &var );
924 require_action( ok, exit, err = kDNSServiceErr_Unknown );
925
926 eventManager->Fire_QueryRecordAnswered( service, ( DNSSDFlags ) flags, ifIndex, fullName, ( DNSSDRRType ) rrtype, ( DNSSDRRClass ) rrclass, var, ttl );
927 }
928
929 exit:
930
931 return;
932 }
933
934
935 void DNSSD_API
936 CDNSSDService::GetAddrInfoReply
937 (
938 DNSServiceRef sdRef,
939 DNSServiceFlags flags,
940 uint32_t ifIndex,
941 DNSServiceErrorType errorCode,
942 const char *hostNameUTF8,
943 const struct sockaddr *rawAddress,
944 uint32_t ttl,
945 void *context
946 )
947 {
948 CComObject<CDNSSDService> * service = NULL;
949 CDNSSDEventManager * eventManager = NULL;
950 int err = 0;
951
952 service = ( CComObject< CDNSSDService>* ) context;
953 require_action( service, exit, err = kDNSServiceErr_Unknown );
954
955 if ( service->ShouldHandleReply( errorCode, eventManager ) )
956 {
957 CComBSTR hostName;
958 DWORD sockaddrLen;
959 DNSSDAddressFamily addressFamily;
960 char addressUTF8[INET6_ADDRSTRLEN];
961 DWORD addressLen = sizeof( addressUTF8 );
962 CComBSTR address;
963 BOOL ok;
964
965 ok = UTF8ToBSTR( hostNameUTF8, hostName );
966 require_action( ok, exit, err = kDNSServiceErr_Unknown );
967
968 switch ( rawAddress->sa_family )
969 {
970 case AF_INET:
971 {
972 addressFamily = kDNSSDAddressFamily_IPv4;
973 sockaddrLen = sizeof( sockaddr_in );
974 }
975 break;
976
977 case AF_INET6:
978 {
979 addressFamily = kDNSSDAddressFamily_IPv6;
980 sockaddrLen = sizeof( sockaddr_in6 );
981 }
982 break;
983 }
984
985 err = WSAAddressToStringA( ( LPSOCKADDR ) rawAddress, sockaddrLen, NULL, addressUTF8, &addressLen );
986 require_noerr( err, exit );
987 ok = UTF8ToBSTR( addressUTF8, address );
988 require_action( ok, exit, err = kDNSServiceErr_Unknown );
989
990 eventManager->Fire_AddressFound( service, ( DNSSDFlags ) flags, ifIndex, hostName, addressFamily, address, ttl );
991 }
992
993 exit:
994
995 return;
996 }
997
998
999 void DNSSD_API
1000 CDNSSDService::NATPortMappingReply
1001 (
1002 DNSServiceRef sdRef,
1003 DNSServiceFlags flags,
1004 uint32_t ifIndex,
1005 DNSServiceErrorType errorCode,
1006 uint32_t externalAddress, /* four byte IPv4 address in network byte order */
1007 DNSServiceProtocol protocol,
1008 uint16_t internalPort,
1009 uint16_t externalPort, /* may be different than the requested port */
1010 uint32_t ttl, /* may be different than the requested ttl */
1011 void *context
1012 )
1013 {
1014 CComObject<CDNSSDService> * service = NULL;
1015 CDNSSDEventManager * eventManager = NULL;
1016 int err = 0;
1017
1018 service = ( CComObject< CDNSSDService>* ) context;
1019 require_action( service, exit, err = kDNSServiceErr_Unknown );
1020
1021 if ( service->ShouldHandleReply( errorCode, eventManager ) )
1022 {
1023 eventManager->Fire_MappingCreated( service, ( DNSSDFlags ) flags, ifIndex, externalAddress, ( DNSSDAddressFamily ) ( protocol & 0x8 ), ( DNSSDProtocol ) ( protocol & 0x80 ), ntohs( internalPort ), ntohs( externalPort ), ttl );
1024 }
1025
1026 exit:
1027
1028 return;
1029 }
1030
1031
1032 void DNSSD_API
1033 CDNSSDService::RegisterRecordReply
1034 (
1035 DNSServiceRef sdRef,
1036 DNSRecordRef RecordRef,
1037 DNSServiceFlags flags,
1038 DNSServiceErrorType errorCode,
1039 void *context
1040 )
1041 {
1042 CComObject<CDNSSDRecord> * record = NULL;
1043 CDNSSDService * service = NULL;
1044 CDNSSDEventManager * eventManager = NULL;
1045 int err = 0;
1046
1047 record = ( CComObject< CDNSSDRecord >* ) context;
1048 require_action( record, exit, err = kDNSServiceErr_Unknown );
1049 service = record->GetServiceObject();
1050 require_action( service, exit, err = kDNSServiceErr_Unknown );
1051
1052 if ( service->ShouldHandleReply( errorCode, eventManager ) )
1053 {
1054 eventManager->Fire_RecordRegistered( record, ( DNSSDFlags ) flags );
1055 }
1056
1057 exit:
1058
1059 return;
1060 }
1061
1062
1063 BOOL
1064 CDNSSDService::ShouldHandleReply( DNSServiceErrorType errorCode, CDNSSDEventManager *& eventManager )
1065 {
1066 BOOL ok = FALSE;
1067
1068 if ( !this->Stopped() )
1069 {
1070 eventManager = this->GetEventManager();
1071 require_action( eventManager, exit, ok = FALSE );
1072
1073 if ( !errorCode )
1074 {
1075 ok = TRUE;
1076 }
1077 else
1078 {
1079 eventManager->Fire_OperationFailed( this, ( DNSSDError ) errorCode );
1080 }
1081 }
1082
1083 exit:
1084
1085 return ok;
1086 }
1087
1088
1089 LRESULT CALLBACK
1090 CDNSSDService::WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
1091 {
1092 if ( msg == WM_SOCKET )
1093 {
1094 SocketMap::iterator it;
1095
1096 it = m_socketMap.find( ( SOCKET ) wParam );
1097 check( it != m_socketMap.end() );
1098
1099 if ( it != m_socketMap.end() )
1100 {
1101 DNSServiceProcessResult( it->second->m_primary );
1102 }
1103 }
1104
1105 return DefWindowProc(hWnd, msg, wParam, lParam);;
1106 }