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
18
19
20 #pragma warning(disable:4995)
21
22
23
24 #include "stdafx.h"
25
26 #include <strsafe.h>
27
28 #include "DNSSDService.h"
29
30 #include "DNSSDEventManager.h"
31
32 #include "DNSSDRecord.h"
33
34 #include "TXTRecord.h"
35
36 #include "StringServices.h"
37
38 #include <DebugServices.h>
39
40
41
42
43
44 #define WM_SOCKET (WM_APP + 100)
45
46
47
48
49
50 // CDNSSDService
51
52
53
54 BOOL CDNSSDService::m_registeredWindowClass = FALSE;
55
56 HWND CDNSSDService::m_hiddenWindow = NULL;
57
58 CDNSSDService::SocketMap CDNSSDService::m_socketMap;
59
60
61
62
63
FinalConstruct()64 HRESULT CDNSSDService::FinalConstruct()
65
66 {
67
68 DNSServiceErrorType err = 0;
69
70 HRESULT hr = S_OK;
71
72
73
74 m_isPrimary = TRUE;
75
76 err = DNSServiceCreateConnection( &m_primary );
77
78 require_action( !err, exit, hr = E_FAIL );
79
80
81
82 if ( !m_hiddenWindow )
83
84 {
85
86 TCHAR windowClassName[ 256 ];
87
88
89
90 StringCchPrintf( windowClassName, sizeof( windowClassName ) / sizeof( TCHAR ), TEXT( "Bonjour Hidden Window %d" ), GetProcessId( NULL ) );
91
92
93
94 if ( !m_registeredWindowClass )
95
96 {
97
98 WNDCLASS wc;
99
100 ATOM atom;
101
102
103
104 wc.style = 0;
105
106 wc.lpfnWndProc = WndProc;
107
108 wc.cbClsExtra = 0;
109
110 wc.cbWndExtra = 0;
111
112 wc.hInstance = NULL;
113
114 wc.hIcon = NULL;
115
116 wc.hCursor = NULL;
117
118 wc.hbrBackground = NULL;
119
120 wc.lpszMenuName = NULL;
121
122 wc.lpszClassName = windowClassName;
123
124
125
126 atom = RegisterClass(&wc);
127
128 require_action( atom != NULL, exit, hr = E_FAIL );
129
130
131
132 m_registeredWindowClass = TRUE;
133
134 }
135
136
137
138 m_hiddenWindow = CreateWindow( windowClassName, windowClassName, WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL, GetModuleHandle( NULL ), NULL );
139
140 require_action( m_hiddenWindow != NULL, exit, hr = E_FAIL );
141
142 }
143
144
145
146 err = WSAAsyncSelect( DNSServiceRefSockFD( m_primary ), m_hiddenWindow, WM_SOCKET, FD_READ );
147
148 require_action( !err, exit, hr = E_FAIL );
149
150
151
152 m_socketMap[ DNSServiceRefSockFD( m_primary ) ] = this;
153
154
155
156 exit:
157
158
159
160 return hr;
161
162 }
163
164
165
166
167
FinalRelease()168 void CDNSSDService::FinalRelease()
169
170 {
171
172 dlog( kDebugLevelTrace, "FinalRelease()\n" );
173
174 Stop();
175
176 }
177
178
179
180
181
EnumerateDomains(DNSSDFlags flags,ULONG ifIndex,IDNSSDEventManager * eventManager,IDNSSDService ** service)182 STDMETHODIMP CDNSSDService::EnumerateDomains(DNSSDFlags flags, ULONG ifIndex, IDNSSDEventManager *eventManager, IDNSSDService **service)
183
184 {
185
186 CComObject<CDNSSDService> * object = NULL;
187
188 DNSServiceRef subord = NULL;
189
190 DNSServiceErrorType err = 0;
191
192 HRESULT hr = 0;
193
194
195
196 check( m_primary );
197
198
199
200 // Initialize
201
202 *service = NULL;
203
204
205
206 try
207
208 {
209
210 object = new CComObject<CDNSSDService>();
211
212 }
213
214 catch ( ... )
215
216 {
217
218 object = NULL;
219
220 }
221
222
223
224 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
225
226 object->AddRef();
227
228
229
230 subord = m_primary;
231
232 err = DNSServiceEnumerateDomains( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, ( DNSServiceDomainEnumReply ) &DomainEnumReply, object );
233
234 require_noerr( err, exit );
235
236
237
238 object->SetPrimaryRef( m_primary );
239
240 object->SetSubordRef( subord );
241
242 object->SetEventManager( eventManager );
243
244
245
246 *service = object;
247
248
249
250 exit:
251
252
253
254 if ( err && object )
255
256 {
257
258 object->Release();
259
260 }
261
262
263
264 return err;
265
266 }
267
268
269
270
271
Browse(DNSSDFlags flags,ULONG ifIndex,BSTR regtype,BSTR domain,IDNSSDEventManager * eventManager,IDNSSDService ** service)272 STDMETHODIMP CDNSSDService::Browse(DNSSDFlags flags, ULONG ifIndex, BSTR regtype, BSTR domain, IDNSSDEventManager* eventManager, IDNSSDService** service )
273
274 {
275
276 CComObject<CDNSSDService> * object = NULL;
277
278 std::string regtypeUTF8;
279
280 std::string domainUTF8;
281
282 DNSServiceRef subord = NULL;
283
284 DNSServiceErrorType err = 0;
285
286 HRESULT hr = 0;
287
288 BOOL ok;
289
290
291
292 check( m_primary );
293
294
295
296 // Initialize
297
298 *service = NULL;
299
300
301
302 // Convert BSTR params to utf8
303
304 ok = BSTRToUTF8( regtype, regtypeUTF8 );
305
306 require_action( ok, exit, err = kDNSServiceErr_BadParam );
307
308 ok = BSTRToUTF8( domain, domainUTF8 );
309
310 require_action( ok, exit, err = kDNSServiceErr_BadParam );
311
312
313
314 try
315
316 {
317
318 object = new CComObject<CDNSSDService>();
319
320 }
321
322 catch ( ... )
323
324 {
325
326 object = NULL;
327
328 }
329
330
331
332 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
333
334 object->AddRef();
335
336
337
338 subord = m_primary;
339
340 err = DNSServiceBrowse( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, regtypeUTF8.c_str(), ( domainUTF8.size() > 0 ) ? domainUTF8.c_str() : NULL, ( DNSServiceBrowseReply ) &BrowseReply, object );
341
342 require_noerr( err, exit );
343
344
345
346 object->SetPrimaryRef( m_primary );
347
348 object->SetSubordRef( subord );
349
350 object->SetEventManager( eventManager );
351
352
353
354 *service = object;
355
356
357
358 exit:
359
360
361
362 if ( err && object )
363
364 {
365
366 object->Release();
367
368 }
369
370
371
372 return err;
373
374 }
375
376
377
378
379
Resolve(DNSSDFlags flags,ULONG ifIndex,BSTR serviceName,BSTR regType,BSTR domain,IDNSSDEventManager * eventManager,IDNSSDService ** service)380 STDMETHODIMP CDNSSDService::Resolve(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, IDNSSDEventManager* eventManager, IDNSSDService** service)
381
382 {
383
384 CComObject<CDNSSDService> * object = NULL;
385
386 std::string serviceNameUTF8;
387
388 std::string regTypeUTF8;
389
390 std::string domainUTF8;
391
392 DNSServiceRef subord = NULL;
393
394 DNSServiceErrorType err = 0;
395
396 HRESULT hr = 0;
397
398 BOOL ok;
399
400
401
402 check( m_primary );
403
404
405
406 // Initialize
407
408 *service = NULL;
409
410
411
412 // Convert BSTR params to utf8
413
414 ok = BSTRToUTF8( serviceName, serviceNameUTF8 );
415
416 require_action( ok, exit, err = kDNSServiceErr_BadParam );
417
418 ok = BSTRToUTF8( regType, regTypeUTF8 );
419
420 require_action( ok, exit, err = kDNSServiceErr_BadParam );
421
422 ok = BSTRToUTF8( domain, domainUTF8 );
423
424 require_action( ok, exit, err = kDNSServiceErr_BadParam );
425
426
427
428 try
429
430 {
431
432 object = new CComObject<CDNSSDService>();
433
434 }
435
436 catch ( ... )
437
438 {
439
440 object = NULL;
441
442 }
443
444
445
446 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
447
448 object->AddRef();
449
450
451
452 subord = m_primary;
453
454 err = DNSServiceResolve( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, serviceNameUTF8.c_str(), regTypeUTF8.c_str(), domainUTF8.c_str(), ( DNSServiceResolveReply ) &ResolveReply, object );
455
456 require_noerr( err, exit );
457
458
459
460 object->SetPrimaryRef( m_primary );
461
462 object->SetSubordRef( subord );
463
464 object->SetEventManager( eventManager );
465
466
467
468 *service = object;
469
470
471
472 exit:
473
474
475
476 if ( err && object )
477
478 {
479
480 object->Release();
481
482 }
483
484
485
486 return err;
487
488 }
489
490
491
492
493
Register(DNSSDFlags flags,ULONG ifIndex,BSTR serviceName,BSTR regType,BSTR domain,BSTR host,USHORT port,ITXTRecord * record,IDNSSDEventManager * eventManager,IDNSSDService ** service)494 STDMETHODIMP CDNSSDService::Register(DNSSDFlags flags, ULONG ifIndex, BSTR serviceName, BSTR regType, BSTR domain, BSTR host, USHORT port, ITXTRecord *record, IDNSSDEventManager *eventManager, IDNSSDService **service)
495
496 {
497
498 CComObject<CDNSSDService> * object = NULL;
499
500 std::string serviceNameUTF8;
501
502 std::string regTypeUTF8;
503
504 std::string domainUTF8;
505
506 std::string hostUTF8;
507
508 const void * txtRecord = NULL;
509
510 uint16_t txtLen = 0;
511
512 DNSServiceRef subord = NULL;
513
514 DNSServiceErrorType err = 0;
515
516 HRESULT hr = 0;
517
518 BOOL ok;
519
520
521
522 check( m_primary );
523
524
525
526 // Initialize
527
528 *service = NULL;
529
530
531
532 // Convert BSTR params to utf8
533
534 ok = BSTRToUTF8( serviceName, serviceNameUTF8 );
535
536 require_action( ok, exit, err = kDNSServiceErr_BadParam );
537
538 ok = BSTRToUTF8( regType, regTypeUTF8 );
539
540 require_action( ok, exit, err = kDNSServiceErr_BadParam );
541
542 ok = BSTRToUTF8( domain, domainUTF8 );
543
544 require_action( ok, exit, err = kDNSServiceErr_BadParam );
545
546 ok = BSTRToUTF8( host, hostUTF8 );
547
548 require_action( ok, exit, err = kDNSServiceErr_BadParam );
549
550
551
552 try
553
554 {
555
556 object = new CComObject<CDNSSDService>();
557
558 }
559
560 catch ( ... )
561
562 {
563
564 object = NULL;
565
566 }
567
568
569
570 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
571
572 object->AddRef();
573
574
575
576 if ( record )
577
578 {
579
580 CComObject< CTXTRecord > * realTXTRecord;
581
582
583
584 realTXTRecord = ( CComObject< CTXTRecord >* ) record;
585
586
587
588 txtRecord = realTXTRecord->GetBytes();
589
590 txtLen = realTXTRecord->GetLen();
591
592 }
593
594
595
596 subord = m_primary;
597
598 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 );
599
600 require_noerr( err, exit );
601
602
603
604 object->SetPrimaryRef( m_primary );
605
606 object->SetSubordRef( subord );
607
608 object->SetEventManager( eventManager );
609
610
611
612 *service = object;
613
614
615
616 exit:
617
618
619
620 if ( err && object )
621
622 {
623
624 object->Release();
625
626 }
627
628
629
630 return err;
631
632 }
633
634
635
636
637
QueryRecord(DNSSDFlags flags,ULONG ifIndex,BSTR fullname,DNSSDRRType rrtype,DNSSDRRClass rrclass,IDNSSDEventManager * eventManager,IDNSSDService ** service)638 STDMETHODIMP CDNSSDService::QueryRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullname, DNSSDRRType rrtype, DNSSDRRClass rrclass, IDNSSDEventManager *eventManager, IDNSSDService **service)
639
640 {
641
642 CComObject<CDNSSDService> * object = NULL;
643
644 DNSServiceRef subord = NULL;
645
646 std::string fullNameUTF8;
647
648 DNSServiceErrorType err = 0;
649
650 HRESULT hr = 0;
651
652 BOOL ok;
653
654
655
656 check( m_primary );
657
658
659
660 // Initialize
661
662 *service = NULL;
663
664
665
666 // Convert BSTR params to utf8
667
668 ok = BSTRToUTF8( fullname, fullNameUTF8 );
669
670 require_action( ok, exit, err = kDNSServiceErr_BadParam );
671
672
673
674 try
675
676 {
677
678 object = new CComObject<CDNSSDService>();
679
680 }
681
682 catch ( ... )
683
684 {
685
686 object = NULL;
687
688 }
689
690
691
692 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
693
694 object->AddRef();
695
696
697
698 subord = m_primary;
699
700 err = DNSServiceQueryRecord( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, fullNameUTF8.c_str(), ( uint16_t ) rrtype, ( uint16_t ) rrclass, ( DNSServiceQueryRecordReply ) &QueryRecordReply, object );
701
702 require_noerr( err, exit );
703
704
705
706 object->SetPrimaryRef( m_primary );
707
708 object->SetSubordRef( subord );
709
710 object->SetEventManager( eventManager );
711
712
713
714 *service = object;
715
716
717
718 exit:
719
720
721
722 if ( err && object )
723
724 {
725
726 object->Release();
727
728 }
729
730
731
732 return err;
733
734 }
735
736
737
738
739
RegisterRecord(DNSSDFlags flags,ULONG ifIndex,BSTR fullName,DNSSDRRType rrtype,DNSSDRRClass rrclass,VARIANT rdata,ULONG ttl,IDNSSDEventManager * eventManager,IDNSSDRecord ** record)740 STDMETHODIMP CDNSSDService::RegisterRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullName, DNSSDRRType rrtype, DNSSDRRClass rrclass, VARIANT rdata, ULONG ttl, IDNSSDEventManager* eventManager, IDNSSDRecord** record)
741
742 {
743
744 CComObject<CDNSSDRecord> * object = NULL;
745
746 DNSRecordRef rref = NULL;
747
748 std::string fullNameUTF8;
749
750 std::vector< BYTE > byteArray;
751
752 const void * byteArrayPtr = NULL;
753
754 DNSServiceErrorType err = 0;
755
756 HRESULT hr = 0;
757
758 BOOL ok;
759
760
761
762 check( m_primary );
763
764
765
766 // Initialize
767
768 *object = NULL;
769
770
771
772 // Convert BSTR params to utf8
773
774 ok = BSTRToUTF8( fullName, fullNameUTF8 );
775
776 require_action( ok, exit, err = kDNSServiceErr_BadParam );
777
778
779
780 // Convert the VARIANT
781
782 ok = VariantToByteArray( &rdata, byteArray );
783
784 require_action( ok, exit, err = kDNSServiceErr_Unknown );
785
786
787
788 try
789
790 {
791
792 object = new CComObject<CDNSSDRecord>();
793
794 }
795
796 catch ( ... )
797
798 {
799
800 object = NULL;
801
802 }
803
804
805
806 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
807
808 object->AddRef();
809
810
811
812 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 );
813
814 require_noerr( err, exit );
815
816
817
818 object->SetServiceObject( this );
819
820 object->SetRecordRef( rref );
821
822 this->SetEventManager( eventManager );
823
824
825
826 *record = object;
827
828
829
830 exit:
831
832
833
834 if ( err && object )
835
836 {
837
838 object->Release();
839
840 }
841
842
843
844 return err;
845
846 }
847
848
849
850
851
AddRecord(DNSSDFlags flags,DNSSDRRType rrtype,VARIANT rdata,ULONG ttl,IDNSSDRecord ** record)852 STDMETHODIMP CDNSSDService::AddRecord(DNSSDFlags flags, DNSSDRRType rrtype, VARIANT rdata, ULONG ttl, IDNSSDRecord ** record)
853
854 {
855
856 CComObject<CDNSSDRecord> * object = NULL;
857
858 DNSRecordRef rref = NULL;
859
860 std::vector< BYTE > byteArray;
861
862 const void * byteArrayPtr = NULL;
863
864 DNSServiceErrorType err = 0;
865
866 HRESULT hr = 0;
867
868 BOOL ok;
869
870
871
872 check( m_primary );
873
874
875
876 // Initialize
877
878 *object = NULL;
879
880
881
882 // Convert the VARIANT
883
884 ok = VariantToByteArray( &rdata, byteArray );
885
886 require_action( ok, exit, err = kDNSServiceErr_Unknown );
887
888
889
890 try
891
892 {
893
894 object = new CComObject<CDNSSDRecord>();
895
896 }
897
898 catch ( ... )
899
900 {
901
902 object = NULL;
903
904 }
905
906
907
908 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
909
910 object->AddRef();
911
912
913
914 err = DNSServiceAddRecord( m_primary, &rref, flags, rrtype, ( uint16_t ) byteArray.size(), byteArray.size() > 0 ? &byteArray[ 0 ] : NULL, ttl );
915
916 require_noerr( err, exit );
917
918
919
920 object->SetServiceObject( this );
921
922 object->SetRecordRef( rref );
923
924
925
926 *record = object;
927
928
929
930 exit:
931
932
933
934 if ( err && object )
935
936 {
937
938 object->Release();
939
940 }
941
942
943
944 return err;
945
946 }
947
948
949
ReconfirmRecord(DNSSDFlags flags,ULONG ifIndex,BSTR fullName,DNSSDRRType rrtype,DNSSDRRClass rrclass,VARIANT rdata)950 STDMETHODIMP CDNSSDService::ReconfirmRecord(DNSSDFlags flags, ULONG ifIndex, BSTR fullName, DNSSDRRType rrtype, DNSSDRRClass rrclass, VARIANT rdata)
951
952 {
953
954 std::string fullNameUTF8;
955
956 std::vector< BYTE > byteArray;
957
958 const void * byteArrayPtr = NULL;
959
960 DNSServiceErrorType err = 0;
961
962 HRESULT hr = 0;
963
964 BOOL ok;
965
966
967
968 // Convert BSTR params to utf8
969
970 ok = BSTRToUTF8( fullName, fullNameUTF8 );
971
972 require_action( ok, exit, err = kDNSServiceErr_BadParam );
973
974
975
976 // Convert the VARIANT
977
978 ok = VariantToByteArray( &rdata, byteArray );
979
980 require_action( ok, exit, err = kDNSServiceErr_Unknown );
981
982
983
984 err = DNSServiceReconfirmRecord( flags, ifIndex, fullNameUTF8.c_str(), rrtype, rrclass, ( uint16_t ) byteArray.size(), byteArray.size() > 0 ? &byteArray[ 0 ] : NULL );
985
986 require_noerr( err, exit );
987
988
989
990 exit:
991
992
993
994 return err;
995
996 }
997
998
999
1000
1001
GetProperty(BSTR prop,VARIANT * value)1002 STDMETHODIMP CDNSSDService::GetProperty(BSTR prop, VARIANT * value )
1003
1004 {
1005
1006 std::string propUTF8;
1007
1008 std::vector< BYTE > byteArray;
1009
1010 SAFEARRAY * psa = NULL;
1011
1012 BYTE * pData = NULL;
1013
1014 uint32_t elems = 0;
1015
1016 DNSServiceErrorType err = 0;
1017
1018 BOOL ok = TRUE;
1019
1020
1021
1022 // Convert BSTR params to utf8
1023
1024 ok = BSTRToUTF8( prop, propUTF8 );
1025
1026 require_action( ok, exit, err = kDNSServiceErr_BadParam );
1027
1028
1029
1030 // Setup the byte array
1031
1032 require_action( V_VT( value ) == ( VT_ARRAY|VT_UI1 ), exit, err = kDNSServiceErr_Unknown );
1033
1034 psa = V_ARRAY( value );
1035
1036 require_action( psa, exit, err = kDNSServiceErr_Unknown );
1037
1038 require_action( SafeArrayGetDim( psa ) == 1, exit, err = kDNSServiceErr_Unknown );
1039
1040 byteArray.reserve( psa->rgsabound[0].cElements );
1041
1042 byteArray.assign( byteArray.capacity(), 0 );
1043
1044 elems = ( uint32_t ) byteArray.capacity();
1045
1046
1047
1048 // Call the function and package the return value in the Variant
1049
1050 err = DNSServiceGetProperty( propUTF8.c_str(), &byteArray[ 0 ], &elems );
1051
1052 require_noerr( err, exit );
1053
1054 ok = ByteArrayToVariant( &byteArray[ 0 ], elems, value );
1055
1056 require_action( ok, exit, err = kDNSSDError_Unknown );
1057
1058
1059
1060 exit:
1061
1062
1063
1064 if ( psa )
1065
1066 {
1067
1068 SafeArrayUnaccessData( psa );
1069
1070 psa = NULL;
1071
1072 }
1073
1074
1075
1076 return err;
1077
1078 }
1079
1080
1081
GetAddrInfo(DNSSDFlags flags,ULONG ifIndex,DNSSDAddressFamily addressFamily,BSTR hostName,IDNSSDEventManager * eventManager,IDNSSDService ** service)1082 STDMETHODIMP CDNSSDService::GetAddrInfo(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, BSTR hostName, IDNSSDEventManager *eventManager, IDNSSDService **service)
1083
1084 {
1085
1086 CComObject<CDNSSDService> * object = NULL;
1087
1088 DNSServiceRef subord = NULL;
1089
1090 std::string hostNameUTF8;
1091
1092 DNSServiceErrorType err = 0;
1093
1094 HRESULT hr = 0;
1095
1096 BOOL ok;
1097
1098
1099
1100 check( m_primary );
1101
1102
1103
1104 // Initialize
1105
1106 *service = NULL;
1107
1108
1109
1110 // Convert BSTR params to utf8
1111
1112 ok = BSTRToUTF8( hostName, hostNameUTF8 );
1113
1114 require_action( ok, exit, err = kDNSServiceErr_BadParam );
1115
1116
1117
1118 try
1119
1120 {
1121
1122 object = new CComObject<CDNSSDService>();
1123
1124 }
1125
1126 catch ( ... )
1127
1128 {
1129
1130 object = NULL;
1131
1132 }
1133
1134
1135
1136 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
1137
1138 object->AddRef();
1139
1140
1141
1142 subord = m_primary;
1143
1144 err = DNSServiceGetAddrInfo( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, addressFamily, hostNameUTF8.c_str(), ( DNSServiceGetAddrInfoReply ) &GetAddrInfoReply, object );
1145
1146 require_noerr( err, exit );
1147
1148
1149
1150 object->SetPrimaryRef( m_primary );
1151
1152 object->SetSubordRef( subord );
1153
1154 object->SetEventManager( eventManager );
1155
1156
1157
1158 *service = object;
1159
1160
1161
1162 exit:
1163
1164
1165
1166 if ( err && object )
1167
1168 {
1169
1170 object->Release();
1171
1172 }
1173
1174
1175
1176 return err;
1177
1178 }
1179
1180
1181
1182
1183
NATPortMappingCreate(DNSSDFlags flags,ULONG ifIndex,DNSSDAddressFamily addressFamily,DNSSDProtocol protocol,USHORT internalPort,USHORT externalPort,ULONG ttl,IDNSSDEventManager * eventManager,IDNSSDService ** service)1184 STDMETHODIMP CDNSSDService::NATPortMappingCreate(DNSSDFlags flags, ULONG ifIndex, DNSSDAddressFamily addressFamily, DNSSDProtocol protocol, USHORT internalPort, USHORT externalPort, ULONG ttl, IDNSSDEventManager *eventManager, IDNSSDService **service)
1185
1186 {
1187
1188 CComObject<CDNSSDService> * object = NULL;
1189
1190 DNSServiceRef subord = NULL;
1191
1192 DNSServiceProtocol prot = 0;
1193
1194 DNSServiceErrorType err = 0;
1195
1196 HRESULT hr = 0;
1197
1198
1199
1200 check( m_primary );
1201
1202
1203
1204 // Initialize
1205
1206 *service = NULL;
1207
1208
1209
1210 try
1211
1212 {
1213
1214 object = new CComObject<CDNSSDService>();
1215
1216 }
1217
1218 catch ( ... )
1219
1220 {
1221
1222 object = NULL;
1223
1224 }
1225
1226
1227
1228 require_action( object != NULL, exit, err = kDNSServiceErr_NoMemory );
1229
1230 object->AddRef();
1231
1232
1233
1234 prot = ( addressFamily | protocol );
1235
1236
1237
1238 subord = m_primary;
1239
1240 err = DNSServiceNATPortMappingCreate( &subord, flags | kDNSServiceFlagsShareConnection, ifIndex, prot, htons( internalPort ), htons( externalPort ), ttl, ( DNSServiceNATPortMappingReply ) &NATPortMappingReply, object );
1241
1242 require_noerr( err, exit );
1243
1244
1245
1246 object->SetPrimaryRef( m_primary );
1247
1248 object->SetSubordRef( subord );
1249
1250 object->SetEventManager( eventManager );
1251
1252
1253
1254 *service = object;
1255
1256
1257
1258 exit:
1259
1260
1261
1262 if ( err && object )
1263
1264 {
1265
1266 object->Release();
1267
1268 }
1269
1270
1271
1272 return err;
1273
1274 }
1275
1276
1277
1278
1279
Stop(void)1280 STDMETHODIMP CDNSSDService::Stop(void)
1281
1282 {
1283
1284 if ( !m_stopped )
1285
1286 {
1287
1288 m_stopped = TRUE;
1289
1290
1291
1292 dlog( kDebugLevelTrace, "Stop()\n" );
1293
1294
1295
1296 if ( m_isPrimary && m_primary )
1297
1298 {
1299
1300 SocketMap::iterator it;
1301
1302
1303
1304 if ( m_hiddenWindow )
1305
1306 {
1307
1308 WSAAsyncSelect( DNSServiceRefSockFD( m_primary ), m_hiddenWindow, 0, 0 );
1309
1310 }
1311
1312
1313
1314 it = m_socketMap.find( DNSServiceRefSockFD( m_primary ) );
1315
1316
1317
1318 if ( it != m_socketMap.end() )
1319
1320 {
1321
1322 m_socketMap.erase( it );
1323
1324 }
1325
1326
1327
1328 DNSServiceRefDeallocate( m_primary );
1329
1330 m_primary = NULL;
1331
1332 }
1333
1334 else if ( m_subord )
1335
1336 {
1337
1338 DNSServiceRefDeallocate( m_subord );
1339
1340 m_subord = NULL;
1341
1342 }
1343
1344
1345
1346 if ( m_eventManager != NULL )
1347
1348 {
1349
1350 m_eventManager->Release();
1351
1352 m_eventManager = NULL;
1353
1354 }
1355
1356 }
1357
1358
1359
1360 return S_OK;
1361
1362 }
1363
1364
1365
1366
1367
1368 void DNSSD_API
DomainEnumReply(DNSServiceRef sdRef,DNSServiceFlags flags,uint32_t ifIndex,DNSServiceErrorType errorCode,const char * replyDomainUTF8,void * context)1369 CDNSSDService::DomainEnumReply
1370 (
1371 DNSServiceRef sdRef,
1372 DNSServiceFlags flags,
1373 uint32_t ifIndex,
1374 DNSServiceErrorType errorCode,
1375 const char *replyDomainUTF8,
1376 void *context
1377 )
1378
1379 {
1380
1381 CComObject<CDNSSDService> * service = NULL;
1382
1383 CDNSSDEventManager * eventManager = NULL;
1384
1385 int err = 0;
1386
1387
1388
1389 service = ( CComObject< CDNSSDService>* ) context;
1390
1391 require_action( service, exit, err = kDNSServiceErr_Unknown );
1392
1393
1394
1395 if ( service->ShouldHandleReply( errorCode, eventManager ) )
1396
1397 {
1398
1399 CComBSTR replyDomain;
1400
1401 BOOL ok;
1402
1403
1404
1405 ok = UTF8ToBSTR( replyDomainUTF8, replyDomain );
1406
1407 require_action( ok, exit, err = kDNSServiceErr_Unknown );
1408
1409
1410
1411 if ( flags & kDNSServiceFlagsAdd )
1412
1413 {
1414
1415 eventManager->Fire_DomainFound( service, ( DNSSDFlags ) flags, ifIndex, replyDomain );
1416
1417 }
1418
1419 else
1420
1421 {
1422
1423 eventManager->Fire_DomainLost( service, ( DNSSDFlags ) flags, ifIndex, replyDomain );
1424
1425 }
1426
1427 }
1428
1429
1430
1431 exit:
1432
1433
1434
1435 return;
1436
1437 }
1438
1439
1440
1441
1442
1443 void DNSSD_API
BrowseReply(DNSServiceRef sdRef,DNSServiceFlags flags,uint32_t ifIndex,DNSServiceErrorType errorCode,const char * serviceNameUTF8,const char * regTypeUTF8,const char * replyDomainUTF8,void * context)1444 CDNSSDService::BrowseReply
1445 (
1446 DNSServiceRef sdRef,
1447 DNSServiceFlags flags,
1448 uint32_t ifIndex,
1449 DNSServiceErrorType errorCode,
1450 const char *serviceNameUTF8,
1451 const char *regTypeUTF8,
1452 const char *replyDomainUTF8,
1453 void *context
1454 )
1455
1456 {
1457
1458 CComObject<CDNSSDService> * service = NULL;
1459
1460 CDNSSDEventManager * eventManager = NULL;
1461
1462 int err = 0;
1463
1464
1465
1466 service = ( CComObject< CDNSSDService>* ) context;
1467
1468 require_action( service, exit, err = kDNSServiceErr_Unknown );
1469
1470
1471
1472 if ( service->ShouldHandleReply( errorCode, eventManager ) )
1473
1474 {
1475
1476 CComBSTR serviceName;
1477
1478 CComBSTR regType;
1479
1480 CComBSTR replyDomain;
1481
1482
1483
1484 UTF8ToBSTR( serviceNameUTF8, serviceName );
1485
1486 UTF8ToBSTR( regTypeUTF8, regType );
1487
1488 UTF8ToBSTR( replyDomainUTF8, replyDomain );
1489
1490
1491
1492 if ( flags & kDNSServiceFlagsAdd )
1493
1494 {
1495
1496 eventManager->Fire_ServiceFound( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain );
1497
1498 }
1499
1500 else
1501
1502 {
1503
1504 eventManager->Fire_ServiceLost( service, ( DNSSDFlags ) flags, ifIndex, serviceName, regType, replyDomain );
1505
1506 }
1507
1508 }
1509
1510
1511
1512 exit:
1513
1514
1515
1516 return;
1517
1518 }
1519
1520
1521
1522
1523
1524 void DNSSD_API
1525
ResolveReply(DNSServiceRef sdRef,DNSServiceFlags flags,uint32_t ifIndex,DNSServiceErrorType errorCode,const char * fullNameUTF8,const char * hostNameUTF8,uint16_t port,uint16_t txtLen,const unsigned char * txtRecord,void * context)1526 CDNSSDService::ResolveReply
1527
1528 (
1529 DNSServiceRef sdRef,
1530 DNSServiceFlags flags,
1531 uint32_t ifIndex,
1532 DNSServiceErrorType errorCode,
1533 const char *fullNameUTF8,
1534 const char *hostNameUTF8,
1535 uint16_t port,
1536 uint16_t txtLen,
1537 const unsigned char *txtRecord,
1538 void *context
1539
1540 )
1541
1542 {
1543
1544 CComObject<CDNSSDService> * service = NULL;
1545
1546 CDNSSDEventManager * eventManager = NULL;
1547
1548 int err = 0;
1549
1550
1551
1552 service = ( CComObject< CDNSSDService>* ) context;
1553
1554 require_action( service, exit, err = kDNSServiceErr_Unknown );
1555
1556
1557
1558 if ( service->ShouldHandleReply( errorCode, eventManager ) )
1559
1560 {
1561
1562 CComBSTR fullName;
1563
1564 CComBSTR hostName;
1565
1566 CComBSTR regType;
1567
1568 CComBSTR replyDomain;
1569
1570 CComObject< CTXTRecord >* record;
1571
1572 BOOL ok;
1573
1574
1575
1576 ok = UTF8ToBSTR( fullNameUTF8, fullName );
1577
1578 require_action( ok, exit, err = kDNSServiceErr_Unknown );
1579
1580 ok = UTF8ToBSTR( hostNameUTF8, hostName );
1581
1582 require_action( ok, exit, err = kDNSServiceErr_Unknown );
1583
1584
1585
1586 try
1587
1588 {
1589
1590 record = new CComObject<CTXTRecord>();
1591
1592 }
1593
1594 catch ( ... )
1595
1596 {
1597
1598 record = NULL;
1599
1600 }
1601
1602
1603
1604 require_action( record, exit, err = kDNSServiceErr_NoMemory );
1605
1606 record->AddRef();
1607
1608
1609
1610 if ( txtLen > 0 )
1611
1612 {
1613
1614 record->SetBytes( txtRecord, txtLen );
1615
1616 }
1617
1618
1619
1620 eventManager->Fire_ServiceResolved( service, ( DNSSDFlags ) flags, ifIndex, fullName, hostName, ntohs( port ), record );
1621
1622 }
1623
1624
1625
1626 exit:
1627
1628
1629
1630 return;
1631
1632 }
1633
1634
1635
1636
1637
1638 void DNSSD_API
RegisterReply(DNSServiceRef sdRef,DNSServiceFlags flags,DNSServiceErrorType errorCode,const char * serviceNameUTF8,const char * regTypeUTF8,const char * domainUTF8,void * context)1639 CDNSSDService::RegisterReply
1640 (
1641 DNSServiceRef sdRef,
1642 DNSServiceFlags flags,
1643 DNSServiceErrorType errorCode,
1644 const char *serviceNameUTF8,
1645 const char *regTypeUTF8,
1646 const char *domainUTF8,
1647 void *context
1648 )
1649
1650 {
1651
1652 CComObject<CDNSSDService> * service = NULL;
1653
1654 CDNSSDEventManager * eventManager = NULL;
1655
1656 int err = 0;
1657
1658
1659
1660 service = ( CComObject< CDNSSDService>* ) context;
1661
1662 require_action( service, exit, err = kDNSServiceErr_Unknown );
1663
1664
1665
1666 if ( service->ShouldHandleReply( errorCode, eventManager ) )
1667
1668 {
1669
1670 CComBSTR serviceName;
1671
1672 CComBSTR regType;
1673
1674 CComBSTR domain;
1675
1676 BOOL ok;
1677
1678
1679
1680 ok = UTF8ToBSTR( serviceNameUTF8, serviceName );
1681
1682 require_action( ok, exit, err = kDNSServiceErr_Unknown );
1683
1684 ok = UTF8ToBSTR( regTypeUTF8, regType );
1685
1686 require_action( ok, exit, err = kDNSServiceErr_Unknown );
1687
1688 ok = UTF8ToBSTR( domainUTF8, domain );
1689
1690 require_action( ok, exit, err = kDNSServiceErr_Unknown );
1691
1692
1693
1694 eventManager->Fire_ServiceRegistered( service, ( DNSSDFlags ) flags, serviceName, regType, domain );
1695
1696 }
1697
1698
1699
1700 exit:
1701
1702
1703
1704 return;
1705
1706 }
1707
1708
1709
1710
1711
1712 void DNSSD_API
QueryRecordReply(DNSServiceRef sdRef,DNSServiceFlags flags,uint32_t ifIndex,DNSServiceErrorType errorCode,const char * fullNameUTF8,uint16_t rrtype,uint16_t rrclass,uint16_t rdlen,const void * rdata,uint32_t ttl,void * context)1713 CDNSSDService::QueryRecordReply
1714 (
1715 DNSServiceRef sdRef,
1716 DNSServiceFlags flags,
1717 uint32_t ifIndex,
1718 DNSServiceErrorType errorCode,
1719 const char *fullNameUTF8,
1720 uint16_t rrtype,
1721 uint16_t rrclass,
1722 uint16_t rdlen,
1723 const void *rdata,
1724 uint32_t ttl,
1725 void *context
1726 )
1727
1728 {
1729
1730 CComObject<CDNSSDService> * service = NULL;
1731
1732 CDNSSDEventManager * eventManager = NULL;
1733
1734 int err = 0;
1735
1736
1737
1738 service = ( CComObject< CDNSSDService>* ) context;
1739
1740 require_action( service, exit, err = kDNSServiceErr_Unknown );
1741
1742
1743
1744 if ( service->ShouldHandleReply( errorCode, eventManager ) )
1745
1746 {
1747
1748 CComBSTR fullName;
1749
1750 VARIANT var;
1751
1752 BOOL ok;
1753
1754
1755
1756 ok = UTF8ToBSTR( fullNameUTF8, fullName );
1757
1758 require_action( ok, exit, err = kDNSServiceErr_Unknown );
1759
1760 ok = ByteArrayToVariant( rdata, rdlen, &var );
1761
1762 require_action( ok, exit, err = kDNSServiceErr_Unknown );
1763
1764
1765
1766 eventManager->Fire_QueryRecordAnswered( service, ( DNSSDFlags ) flags, ifIndex, fullName, ( DNSSDRRType ) rrtype, ( DNSSDRRClass ) rrclass, var, ttl );
1767
1768 }
1769
1770
1771
1772 exit:
1773
1774
1775
1776 return;
1777
1778 }
1779
1780
1781
1782
1783
1784 void DNSSD_API
GetAddrInfoReply(DNSServiceRef sdRef,DNSServiceFlags flags,uint32_t ifIndex,DNSServiceErrorType errorCode,const char * hostNameUTF8,const struct sockaddr * rawAddress,uint32_t ttl,void * context)1785 CDNSSDService::GetAddrInfoReply
1786 (
1787 DNSServiceRef sdRef,
1788 DNSServiceFlags flags,
1789 uint32_t ifIndex,
1790 DNSServiceErrorType errorCode,
1791 const char *hostNameUTF8,
1792 const struct sockaddr *rawAddress,
1793 uint32_t ttl,
1794 void *context
1795 )
1796
1797 {
1798
1799 CComObject<CDNSSDService> * service = NULL;
1800
1801 CDNSSDEventManager * eventManager = NULL;
1802
1803 int err = 0;
1804
1805
1806
1807 service = ( CComObject< CDNSSDService>* ) context;
1808
1809 require_action( service, exit, err = kDNSServiceErr_Unknown );
1810
1811
1812
1813 if ( service->ShouldHandleReply( errorCode, eventManager ) )
1814
1815 {
1816
1817 CComBSTR hostName;
1818
1819 DWORD sockaddrLen;
1820
1821 DNSSDAddressFamily addressFamily;
1822
1823 char addressUTF8[INET6_ADDRSTRLEN];
1824
1825 DWORD addressLen = sizeof( addressUTF8 );
1826
1827 CComBSTR address;
1828
1829 BOOL ok;
1830
1831
1832
1833 ok = UTF8ToBSTR( hostNameUTF8, hostName );
1834
1835 require_action( ok, exit, err = kDNSServiceErr_Unknown );
1836
1837
1838
1839 switch ( rawAddress->sa_family )
1840
1841 {
1842
1843 case AF_INET:
1844
1845 {
1846
1847 addressFamily = kDNSSDAddressFamily_IPv4;
1848
1849 sockaddrLen = sizeof( sockaddr_in );
1850
1851 }
1852
1853 break;
1854
1855
1856
1857 case AF_INET6:
1858
1859 {
1860
1861 addressFamily = kDNSSDAddressFamily_IPv6;
1862
1863 sockaddrLen = sizeof( sockaddr_in6 );
1864
1865 }
1866
1867 break;
1868
1869 }
1870
1871
1872
1873 err = WSAAddressToStringA( ( LPSOCKADDR ) rawAddress, sockaddrLen, NULL, addressUTF8, &addressLen );
1874
1875 require_noerr( err, exit );
1876
1877 ok = UTF8ToBSTR( addressUTF8, address );
1878
1879 require_action( ok, exit, err = kDNSServiceErr_Unknown );
1880
1881
1882
1883 eventManager->Fire_AddressFound( service, ( DNSSDFlags ) flags, ifIndex, hostName, addressFamily, address, ttl );
1884
1885 }
1886
1887
1888
1889 exit:
1890
1891
1892
1893 return;
1894
1895 }
1896
1897
1898
1899
1900
1901 void DNSSD_API
NATPortMappingReply(DNSServiceRef sdRef,DNSServiceFlags flags,uint32_t ifIndex,DNSServiceErrorType errorCode,uint32_t externalAddress,DNSServiceProtocol protocol,uint16_t internalPort,uint16_t externalPort,uint32_t ttl,void * context)1902 CDNSSDService::NATPortMappingReply
1903 (
1904 DNSServiceRef sdRef,
1905 DNSServiceFlags flags,
1906 uint32_t ifIndex,
1907 DNSServiceErrorType errorCode,
1908 uint32_t externalAddress, /* four byte IPv4 address in network byte order */
1909 DNSServiceProtocol protocol,
1910 uint16_t internalPort,
1911 uint16_t externalPort, /* may be different than the requested port */
1912 uint32_t ttl, /* may be different than the requested ttl */
1913 void *context
1914 )
1915
1916 {
1917
1918 CComObject<CDNSSDService> * service = NULL;
1919
1920 CDNSSDEventManager * eventManager = NULL;
1921
1922 int err = 0;
1923
1924
1925
1926 service = ( CComObject< CDNSSDService>* ) context;
1927
1928 require_action( service, exit, err = kDNSServiceErr_Unknown );
1929
1930
1931
1932 if ( service->ShouldHandleReply( errorCode, eventManager ) )
1933
1934 {
1935
1936 eventManager->Fire_MappingCreated( service, ( DNSSDFlags ) flags, ifIndex, externalAddress, ( DNSSDAddressFamily ) ( protocol & 0x8 ), ( DNSSDProtocol ) ( protocol & 0x80 ), ntohs( internalPort ), ntohs( externalPort ), ttl );
1937
1938 }
1939
1940
1941
1942 exit:
1943
1944
1945
1946 return;
1947
1948 }
1949
1950
1951
1952
1953
1954 void DNSSD_API
RegisterRecordReply(DNSServiceRef sdRef,DNSRecordRef RecordRef,DNSServiceFlags flags,DNSServiceErrorType errorCode,void * context)1955 CDNSSDService::RegisterRecordReply
1956 (
1957 DNSServiceRef sdRef,
1958 DNSRecordRef RecordRef,
1959 DNSServiceFlags flags,
1960 DNSServiceErrorType errorCode,
1961 void *context
1962 )
1963
1964 {
1965
1966 CComObject<CDNSSDRecord> * record = NULL;
1967
1968 CDNSSDService * service = NULL;
1969
1970 CDNSSDEventManager * eventManager = NULL;
1971
1972 int err = 0;
1973
1974
1975
1976 record = ( CComObject< CDNSSDRecord >* ) context;
1977
1978 require_action( record, exit, err = kDNSServiceErr_Unknown );
1979
1980 service = record->GetServiceObject();
1981
1982 require_action( service, exit, err = kDNSServiceErr_Unknown );
1983
1984
1985
1986 if ( service->ShouldHandleReply( errorCode, eventManager ) )
1987
1988 {
1989
1990 eventManager->Fire_RecordRegistered( record, ( DNSSDFlags ) flags );
1991
1992 }
1993
1994
1995
1996 exit:
1997
1998
1999
2000 return;
2001
2002 }
2003
2004
2005
2006
2007
2008 BOOL
2009
ShouldHandleReply(DNSServiceErrorType errorCode,CDNSSDEventManager * & eventManager)2010 CDNSSDService::ShouldHandleReply( DNSServiceErrorType errorCode, CDNSSDEventManager *& eventManager )
2011
2012 {
2013
2014 BOOL ok = FALSE;
2015
2016
2017
2018 if ( !this->Stopped() )
2019
2020 {
2021
2022 eventManager = this->GetEventManager();
2023
2024 require_action( eventManager, exit, ok = FALSE );
2025
2026
2027
2028 if ( !errorCode )
2029
2030 {
2031
2032 ok = TRUE;
2033
2034 }
2035
2036 else
2037
2038 {
2039
2040 eventManager->Fire_OperationFailed( this, ( DNSSDError ) errorCode );
2041
2042 }
2043
2044 }
2045
2046
2047
2048 exit:
2049
2050
2051
2052 return ok;
2053
2054 }
2055
2056
2057
2058
2059
2060 LRESULT CALLBACK
2061
WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)2062 CDNSSDService::WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
2063
2064 {
2065
2066 if ( msg == WM_SOCKET )
2067
2068 {
2069
2070 SocketMap::iterator it;
2071
2072
2073
2074 it = m_socketMap.find( ( SOCKET ) wParam );
2075
2076 check( it != m_socketMap.end() );
2077
2078
2079
2080 if ( it != m_socketMap.end() )
2081
2082 {
2083
2084 DNSServiceProcessResult( it->second->m_primary );
2085
2086 }
2087
2088 }
2089
2090
2091
2092 return DefWindowProc(hWnd, msg, wParam, lParam);;
2093
2094 }
2095
2096