]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSWindows/RMxClient.c
mDNSResponder-66.3.tar.gz
[apple/mdnsresponder.git] / mDNSWindows / RMxClient.c
1 /*
2 * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24
25 Change History (most recent first):
26
27 $Log: RMxClient.c,v $
28 Revision 1.3 2004/04/15 01:00:05 bradley
29 Removed support for automatically querying for A/AAAA records when resolving names. Platforms
30 without .local name resolving support will need to manually query for A/AAAA records as needed.
31
32 Revision 1.2 2004/04/09 21:03:14 bradley
33 Changed port numbers to use network byte order for consistency with other platforms.
34
35 Revision 1.1 2004/01/30 02:35:13 bradley
36 Rendezvous Message Exchange implementation for DNS-SD IPC on Windows.
37
38 */
39
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <string.h>
43
44 #include "CommonServices.h"
45 #include "DebugServices.h"
46
47 #include "DNSSD.h"
48 #include "RMxCommon.h"
49
50 #include "RMxClient.h"
51
52 #ifdef __cplusplus
53 extern "C" {
54 #endif
55
56 #if 0
57 #pragma mark == Constants ==
58 #endif
59
60 //===========================================================================================================================
61 // Constants
62 //===========================================================================================================================
63
64 #define DEBUG_NAME "[RMxClient] "
65
66 #if 0
67 #pragma mark == Structures ==
68 #endif
69
70 //===========================================================================================================================
71 // Structures
72 //===========================================================================================================================
73
74 typedef void ( *DNSServiceRefReleaseCallBack )( DNSServiceRef inRef );
75
76 // DNSServiceRef
77
78 typedef struct _DNSServiceRef_t _DNSServiceRef_t;
79 struct _DNSServiceRef_t
80 {
81 RMxSessionRef session;
82 void * context;
83 DNSRecordRef records;
84
85 union
86 {
87 struct // EnumerateDomains
88 {
89 DNSServiceDomainEnumReply callback;
90
91 } domain;
92
93 struct // Register
94 {
95 DNSServiceRegisterReply callback;
96 uint32_t lastID;
97
98 } reg;
99
100 struct // Browse
101 {
102 DNSServiceBrowseReply callback;
103
104 } browse;
105
106 struct // Resolve
107 {
108 DNSServiceFlags flags;
109 DNSServiceResolveReply callback;
110
111 } resolve;
112
113 struct // CreateConnection
114 {
115 DNSServiceRegisterRecordReply callback;
116 uint32_t lastID;
117
118 } connection;
119
120 struct // QueryRecord
121 {
122 DNSServiceQueryRecordReply callback;
123
124 } query;
125
126 } u;
127 };
128
129 // DNSRecordRef
130
131 typedef struct _DNSRecordRef_t _DNSRecordRef_t;
132 struct _DNSRecordRef_t
133 {
134 DNSRecordRef next;
135 uint32_t id;
136 DNSServiceRegisterRecordReply callback;
137 void * context;
138 };
139
140 #if 0
141 #pragma mark == Prototypes ==
142 #endif
143
144 //===========================================================================================================================
145 // Prototypes
146 //===========================================================================================================================
147
148 // RMx
149
150 DEBUG_LOCAL void RMxClientMessageCallBack( RMxMessage *inMessage );
151
152 // Properties
153
154 DEBUG_LOCAL DNSServiceErrorType
155 DNSServiceCopyPropertyDecodeData_client(
156 DNSPropertyCode inCode,
157 const void * inData,
158 size_t inSize,
159 DNSPropertyData * outData );
160
161 // Domain Enumeration
162
163 DEBUG_LOCAL void DNSServiceEnumerateDomainsReply_client( RMxMessage *inMessage );
164
165 // Service Discovery
166
167 DEBUG_LOCAL void DNSServiceBrowseReply_client( RMxMessage *inMessage );
168
169 DEBUG_LOCAL void DNSServiceResolveReply_client( RMxMessage *inMessage );
170
171 // Service Registration
172
173 DEBUG_LOCAL void DNSServiceRegisterReply_client( RMxMessage *inMessage );
174
175 // Special Purpose
176
177 DEBUG_LOCAL DNSRecordRef DNSServiceConnectionRecordRemove_client( DNSServiceRef inRef, DNSRecordRef inRecordRef );
178 DEBUG_LOCAL void DNSServiceRegisterRecordReply_client( RMxMessage *inMessage );
179 DEBUG_LOCAL void DNSServiceQueryRecordReply_client( RMxMessage *inMessage );
180
181 #if 0
182 #pragma mark -
183 #pragma mark == RMx ==
184 #endif
185
186 //===========================================================================================================================
187 // RMxClientInitialize
188 //===========================================================================================================================
189
190 OSStatus RMxClientInitialize( void )
191 {
192 OSStatus err;
193
194 // Initialize the lower-level layer and indicate it is running.
195
196 err = RMxInitialize();
197 require_noerr( err, exit );
198
199 gRMxState = kRMxStateRun;
200
201 exit:
202 if( err != kNoErr )
203 {
204 RMxClientFinalize();
205 }
206 return( err );
207 }
208
209 //===========================================================================================================================
210 // RMxClientFinalize
211 //===========================================================================================================================
212
213 void RMxClientFinalize( void )
214 {
215 RMxFinalize();
216 }
217
218 //===========================================================================================================================
219 // RMxClientMessageCallBack
220 //===========================================================================================================================
221
222 DEBUG_LOCAL void RMxClientMessageCallBack( RMxMessage *inMessage )
223 {
224 check( inMessage );
225
226 switch( inMessage->opcode )
227 {
228 case kRMxOpCodeInvalid:
229 // The session is closing. We don't delete the DNS-SD object here because the client deletes DNS-SD objects.
230 break;
231
232 case kRMxOpCodeEnumerateDomains:
233 DNSServiceEnumerateDomainsReply_client( inMessage );
234 break;
235
236 case kRMxOpCodeRegister:
237 DNSServiceRegisterReply_client( inMessage );
238 break;
239
240 case kRMxOpCodeBrowse:
241 DNSServiceBrowseReply_client( inMessage );
242 break;
243
244 case kRMxOpCodeResolve:
245 DNSServiceResolveReply_client( inMessage );
246 break;
247
248 case kRMxOpCodeRegisterRecord:
249 DNSServiceRegisterRecordReply_client( inMessage );
250 break;
251
252 case kRMxOpCodeQueryRecord:
253 DNSServiceQueryRecordReply_client( inMessage );
254 break;
255
256 default:
257 dlog( kDebugLevelWarning, DEBUG_NAME "message with unknown opcode received (%d)\n", inMessage->opcode );
258 break;
259 }
260 }
261
262 #if 0
263 #pragma mark -
264 #pragma mark == DNS-SD General ==
265 #endif
266
267 //===========================================================================================================================
268 // DNSServiceRefDeallocate_client
269 //===========================================================================================================================
270
271 void DNSServiceRefDeallocate_client( DNSServiceRef inRef )
272 {
273 OSStatus err;
274
275 dlog( kDebugLevelTrace, "\n" DEBUG_NAME "Deallocate ref=%#p\n", inRef );
276 require_action( inRef, exit, err = kDNSServiceErr_BadReference );
277
278 // Close the session (if not already closed).
279
280 if( inRef->session )
281 {
282 inRef->session->callback = NULL;
283 inRef->session->message.context = NULL;
284
285 err = RMxSessionClose( inRef->session, kEndingErr );
286 check_noerr( err );
287 }
288
289 // Release any outstanding individual records.
290
291 while( inRef->records )
292 {
293 DNSRecordRef record;
294
295 record = inRef->records;
296 inRef->records = record->next;
297
298 free( record );
299 }
300
301 // Release the object itself.
302
303 free( inRef );
304
305 exit:
306 return;
307 }
308
309 //===========================================================================================================================
310 // DNSServiceCheckVersion_client
311 //===========================================================================================================================
312
313 DNSServiceErrorType DNSServiceCheckVersion_client( const char *inServer )
314 {
315 DNSServiceErrorType err;
316 RMxSessionRef session;
317 OSStatus errorCode;
318 uint32_t serverCurrentVersion;
319 uint32_t serverOldestClientVersion;
320 uint32_t serverOldestServerVersion;
321
322 session = NULL;
323 dlog( kDebugLevelTrace, "\n" DEBUG_NAME "CheckVersion\n" );
324
325 // Open a session to the server and send the request. Specify no thread since we are going to manually read the message.
326
327 err = RMxSessionOpen( inServer, kRMxSessionFlagsNoThread, kInvalidSocketRef, NULL, NULL, &session,
328 kRMxOpCodeCheckVersion, "www", kRMxCurrentVersion, kRMxOldestClientVersion, kRMxOldestServerVersion );
329 require_noerr( err, exit );
330
331 // Receive the respons, parse it, and check the versions.
332
333 err = RMxSessionRecvMessage( session, kRMxClientTimeout );
334 require_noerr( err, exit );
335 check( session->message.recvData || ( session->message.recvSize == 0 ) );
336
337 err = RMxUnpack( session->message.recvData, session->message.recvSize, "wwww",
338 &errorCode, &serverCurrentVersion, &serverOldestClientVersion, &serverOldestServerVersion );
339 require_noerr( err, exit );
340
341 err = RMxCheckVersion( kRMxCurrentVersion, kRMxOldestClientVersion, kRMxOldestServerVersion,
342 serverCurrentVersion, serverOldestClientVersion, serverOldestServerVersion );
343 check( err == errorCode );
344 if( ( err == kNoErr ) && ( errorCode != kNoErr ) )
345 {
346 dlog( kDebugLevelWarning, DEBUG_NAME "client/server disagree on versions\n" );
347 err = errorCode;
348 }
349
350 exit:
351 if( session )
352 {
353 RMxSessionClose( session, kEndingErr );
354 }
355 return( err );
356 }
357
358 #if 0
359 #pragma mark -
360 #pragma mark == DNS-SD Properties ==
361 #endif
362
363 //===========================================================================================================================
364 // DNSServiceCopyProperty_client
365 //===========================================================================================================================
366
367 DNSServiceErrorType DNSServiceCopyProperty_client( const char *inServer, DNSPropertyCode inCode, DNSPropertyData *outData )
368 {
369 DNSServiceErrorType err;
370 RMxSessionRef session;
371 OSStatus errorCode;
372 DNSPropertyCode code;
373 const void * data;
374 size_t size;
375
376 session = NULL;
377 dlog( kDebugLevelTrace, "\n" DEBUG_NAME "CopyProperty server=%s, code='%C'\n", inServer ? inServer : "<local>", inCode );
378 require_action( outData, exit, err = kDNSServiceErr_BadParam );
379
380 // Open a session to the server and send the request. Specify no thread since we are going to manually read the message.
381
382 err = RMxSessionOpen( inServer, kRMxSessionFlagsNoThread, kInvalidSocketRef, NULL, NULL, &session,
383 kRMxOpCodeCopyProperty, "w", inCode );
384 require_noerr( err, exit );
385
386 // Receive the response, parse it, and check the versions.
387
388 err = RMxSessionRecvMessage( session, kRMxClientTimeout );
389 require_noerr( err, exit );
390 check( session->message.recvData || ( session->message.recvSize == 0 ) );
391
392 err = RMxUnpack( session->message.recvData, session->message.recvSize, "wwn", &errorCode, &code, &data, &size );
393 require_noerr( err, exit );
394 err = errorCode;
395 require_noerr_quiet( err, exit );
396
397 // Decode the data and fill in the results.
398
399 err = DNSServiceCopyPropertyDecodeData_client( code, data, size, outData );
400 require_noerr( err, exit );
401
402 exit:
403 if( session )
404 {
405 RMxSessionClose( session, kEndingErr );
406 }
407 return( err );
408 }
409
410 //===========================================================================================================================
411 // DNSServiceCopyProperty_client
412 //===========================================================================================================================
413
414 DEBUG_LOCAL DNSServiceErrorType
415 DNSServiceCopyPropertyDecodeData_client(
416 DNSPropertyCode inCode,
417 const void * inData,
418 size_t inSize,
419 DNSPropertyData * outData )
420 {
421 OSStatus err;
422
423 check( outData );
424
425 switch( inCode )
426 {
427 case kDNSPropertyCodeVersion:
428 outData->u.version.clientCurrentVersion = kRMxCurrentVersion;
429 outData->u.version.clientOldestServerVersion = kRMxOldestServerVersion;
430
431 err = RMxUnpack( inData, inSize, "www",
432 &outData->u.version.serverCurrentVersion, &outData->u.version.serverOldestClientVersion, NULL );
433 require_noerr( err, exit );
434 break;
435
436 default:
437 dlog( kDebugLevelError, DEBUG_NAME "CopyPropertyDecodeData unknown property code (%C)\n", inCode );
438 err = kDNSServiceErr_Unsupported;
439 goto exit;
440 }
441 err = kDNSServiceErr_NoError;
442
443 exit:
444 return( err );
445 }
446
447 //===========================================================================================================================
448 // DNSServiceReleaseProperty_client
449 //===========================================================================================================================
450
451 DNSServiceErrorType DNSServiceReleaseProperty_client( DNSPropertyData *inData )
452 {
453 OSStatus err;
454
455 dlog( kDebugLevelTrace, "\n" DEBUG_NAME "ReleaseProperty\n" );
456 require_action( inData, exit, err = kDNSServiceErr_BadParam );
457
458 switch( inData->code )
459 {
460 case kDNSPropertyCodeVersion:
461 // Data is embedded directly in the structure so there is nothing to release.
462 break;
463
464 default:
465 dlog( kDebugLevelError, DEBUG_NAME "ReleaseProperty unknown property code (%C)\n", inData->code );
466 err = kDNSServiceErr_Unsupported;
467 goto exit;
468 }
469 err = kDNSServiceErr_NoError;
470
471 exit:
472 return( err );
473 }
474
475 #if 0
476 #pragma mark -
477 #pragma mark == DNS-SD Domain Enumeration ==
478 #endif
479
480 //===========================================================================================================================
481 // DNSServiceEnumerateDomains_client
482 //===========================================================================================================================
483
484 DNSServiceErrorType
485 DNSServiceEnumerateDomains_client(
486 DNSServiceRef * outRef,
487 const char * inServer,
488 const DNSServiceFlags inFlags,
489 const uint32_t inInterfaceIndex,
490 const DNSServiceDomainEnumReply inCallBack,
491 void * inContext )
492 {
493 DNSServiceErrorType err;
494 DNSServiceRef obj;
495
496 obj = NULL;
497 dlog( kDebugLevelTrace, "\n" DEBUG_NAME "EnumerateDomains flags=0x%08X, ifi=%d, server=%s\n",
498 inFlags, inInterfaceIndex, inServer ? inServer : "<local>" );
499 require_action( outRef, exit, err = kDNSServiceErr_BadParam );
500 require_action( ( inFlags == kDNSServiceFlagsBrowseDomains ) ||
501 ( inFlags == kDNSServiceFlagsRegistrationDomains ),
502 exit, err = kDNSServiceErr_BadFlags );
503 require_action( inCallBack, exit, err = kDNSServiceErr_BadParam );
504
505 obj = (DNSServiceRef) calloc( 1, sizeof( *obj ) );
506 require_action( obj, exit, err = kDNSServiceErr_NoMemory );
507
508 obj->context = inContext;
509 obj->u.domain.callback = inCallBack;
510
511 // Open a session to the server and send the request.
512
513 err = RMxSessionOpen( inServer, kRMxSessionFlagsNoClose, kInvalidSocketRef, RMxClientMessageCallBack, obj,
514 &obj->session, kRMxOpCodeEnumerateDomains, "ww", inFlags, inInterfaceIndex );
515 require_noerr( err, exit );
516
517 // Success!
518
519 *outRef = obj;
520 obj = NULL;
521
522 exit:
523 if( obj )
524 {
525 DNSServiceRefDeallocate_client( obj );
526 }
527 return( err );
528 }
529
530 //===========================================================================================================================
531 // DNSServiceEnumerateDomainsReply_client
532 //===========================================================================================================================
533
534 DEBUG_LOCAL void DNSServiceEnumerateDomainsReply_client( RMxMessage *inMessage )
535 {
536 OSStatus err;
537 DNSServiceRef obj;
538 DNSServiceFlags flags;
539 uint32_t interfaceIndex;
540 DNSServiceErrorType errorCode;
541 const char * domain;
542
543 check( inMessage );
544 obj = (DNSServiceRef) inMessage->context;
545 check( obj );
546
547 err = inMessage->status;
548 if( err == kNoErr )
549 {
550 err = RMxUnpack( inMessage->recvData, inMessage->recvSize, "wwws", &flags, &interfaceIndex, &errorCode, &domain, NULL );
551 check_noerr( err );
552 if( err == kNoErr )
553 {
554 dlog( kDebugLevelTrace, DEBUG_NAME "EnumerateDomains reply flags=0x%08X, ifi=%d, err=%d, domain=\"%s\"\n",
555 flags, interfaceIndex, errorCode, domain );
556
557 obj->u.domain.callback( obj, flags, interfaceIndex, errorCode, domain, obj->context );
558 }
559 }
560 if( err != kNoErr )
561 {
562 obj->u.domain.callback( obj, 0, 0, err, "", obj->context );
563 }
564 }
565
566 #if 0
567 #pragma mark -
568 #pragma mark == DNS-SD Service Registration ==
569 #endif
570
571 //===========================================================================================================================
572 // DNSServiceRegister_direct
573 //===========================================================================================================================
574
575 DNSServiceErrorType
576 DNSServiceRegister_client(
577 DNSServiceRef * outRef,
578 const char * inServer,
579 DNSServiceFlags inFlags,
580 uint32_t inInterfaceIndex,
581 const char * inName,
582 const char * inType,
583 const char * inDomain,
584 const char * inHost,
585 uint16_t inPort,
586 uint16_t inTXTSize,
587 const void * inTXT,
588 DNSServiceRegisterReply inCallBack,
589 void * inContext )
590 {
591 DNSServiceErrorType err;
592 DNSServiceRef obj;
593
594 obj = NULL;
595 dlog( kDebugLevelTrace, "\n" DEBUG_NAME
596 "Resolve flags=0x%08X, ifi=%d, name=\"%s\", type=\"%s\", domain=\"%s\", host=\"%s\", port=%d, txtSize=%d\n",
597 inFlags, inInterfaceIndex, inName ? inName : "<default>", inType, inDomain ? inDomain : "<default>", inHost,
598 ntohs( inPort ), inTXTSize );
599 require_action( outRef, exit, err = kDNSServiceErr_BadReference );
600 require_action( ( inFlags == 0 ) || ( inFlags == kDNSServiceFlagsNoAutoRename ), exit, err = kDNSServiceErr_BadFlags );
601 require_action( inType, exit, err = kDNSServiceErr_BadParam );
602 require_action( inTXT || ( inTXTSize == 0 ), exit, err = kDNSServiceErr_BadParam );
603 require_action( inCallBack, exit, err = kDNSServiceErr_BadParam );
604
605 obj = (DNSServiceRef) calloc( 1, sizeof( *obj ) );
606 require_action( obj, exit, err = kDNSServiceErr_NoMemory );
607
608 obj->context = inContext;
609 obj->u.reg.callback = inCallBack;
610
611 // Open a session to the server and send the request.
612
613 err = RMxSessionOpen( inServer, kRMxSessionFlagsNoClose, kInvalidSocketRef, RMxClientMessageCallBack, obj,
614 &obj->session, kRMxOpCodeRegister, "wwsssshn", inFlags, inInterfaceIndex, inName ? inName : "", inType,
615 inDomain ? inDomain : "", inHost, inPort, inTXTSize, inTXT );
616 require_noerr( err, exit );
617
618 // Success!
619
620 *outRef = obj;
621 obj = NULL;
622
623 exit:
624 if( obj )
625 {
626 DNSServiceRefDeallocate_client( obj );
627 }
628 return( err );
629 }
630
631 //===========================================================================================================================
632 // DNSServiceRegisterReply_client
633 //===========================================================================================================================
634
635 DEBUG_LOCAL void DNSServiceRegisterReply_client( RMxMessage *inMessage )
636 {
637 OSStatus err;
638 DNSServiceRef obj;
639 DNSServiceFlags flags;
640 DNSServiceErrorType errorCode;
641 const char * name;
642 const char * type;
643 const char * domain;
644
645 check( inMessage );
646 obj = (DNSServiceRef) inMessage->context;
647 check( obj );
648
649 err = inMessage->status;
650 if( err == kNoErr )
651 {
652 err = RMxUnpack( inMessage->recvData, inMessage->recvSize, "wwsss",
653 &flags, &errorCode, &name, NULL, &type, NULL, &domain, NULL );
654 check_noerr( err );
655 if( err == kNoErr )
656 {
657 dlog( kDebugLevelTrace, DEBUG_NAME "Register reply flags=0x%08X, err=%d, name=\"%s\", type=\"%s\", domain=\"%s\"\n",
658 flags, errorCode, name, type, domain );
659
660 obj->u.reg.callback( obj, flags, errorCode, name, type, domain, obj->context );
661 }
662 }
663 if( err != kNoErr )
664 {
665 obj->u.reg.callback( obj, 0, err, "", "", "", obj->context );
666 }
667 }
668
669 //===========================================================================================================================
670 // DNSServiceAddRecord_client
671 //===========================================================================================================================
672
673 DNSServiceErrorType
674 DNSServiceAddRecord_client(
675 DNSServiceRef inRef,
676 DNSRecordRef * outRecordRef,
677 DNSServiceFlags inFlags,
678 uint16_t inRRType,
679 uint16_t inRDataSize,
680 const void * inRData,
681 uint32_t inTTL )
682 {
683 DNSServiceErrorType err;
684 DNSRecordRef obj;
685
686 obj = NULL;
687 RMxLock();
688 dlog( kDebugLevelTrace, "\n" DEBUG_NAME "AddRecord flags=0x%08X, rrType=%d, rrDataSize=%d, ttl=%d\n",
689 inFlags, inRRType, inRDataSize, inTTL );
690 require_action( inRef, exit, err = kDNSServiceErr_BadReference );
691 require_action( inRef->session, exit, err = kDNSServiceErr_NotInitialized );
692 require_action( outRecordRef, exit, err = kDNSServiceErr_BadParam );
693 require_action( inFlags == 0, exit, err = kDNSServiceErr_BadFlags );
694 require_action( inRData && ( inRDataSize > 0 ), exit, err = kDNSServiceErr_BadParam );
695
696 // Allocate and initialize the object.
697
698 obj = (DNSRecordRef) calloc( 1, sizeof( *obj ) );
699 require_action( obj, exit, err = kDNSServiceErr_NoMemory );
700
701 // Send the message. Use an ID that should be unique for the session and avoid the reserved ID.
702
703 obj->id = ++inRef->u.reg.lastID;
704 if( obj->id == kDNSRecordIndexDefaultTXT )
705 {
706 obj->id = ++inRef->u.reg.lastID;
707 }
708
709 err = RMxSessionSendMessage( inRef->session, kRMxOpCodeAddRecord, kNoErr, "wwhnw",
710 obj->id, inFlags, inRRType, inRDataSize, inRData, inTTL );
711 require_noerr( err, exit );
712
713 // Success!
714
715 *outRecordRef = obj;
716 obj = NULL;
717
718 exit:
719 if( obj )
720 {
721 free( obj );
722 }
723 RMxUnlock();
724 return( err );
725 }
726
727 //===========================================================================================================================
728 // DNSServiceUpdateRecord_client
729 //===========================================================================================================================
730
731 DNSServiceErrorType
732 DNSServiceUpdateRecord_client(
733 DNSServiceRef inRef,
734 DNSRecordRef inRecordRef,
735 DNSServiceFlags inFlags,
736 uint16_t inRDataSize,
737 const void * inRData,
738 uint32_t inTTL )
739 {
740 DNSServiceErrorType err;
741
742 RMxLock();
743 dlog( kDebugLevelTrace, "\n" DEBUG_NAME "UpdateRecord flags=0x%08X, rrDataSize=%d, ttl=%d\n", inFlags, inRDataSize, inTTL );
744 require_action( inRef, exit, err = kDNSServiceErr_BadReference );
745 require_action( inRef->session, exit, err = kDNSServiceErr_NotInitialized );
746 require_action( inFlags == 0, exit, err = kDNSServiceErr_BadFlags );
747 require_action( inRData && ( inRDataSize > 0 ), exit, err = kDNSServiceErr_BadParam );
748
749 err = RMxSessionSendMessage( inRef->session, kRMxOpCodeUpdateRecord, kNoErr, "wwnw",
750 inRecordRef ? inRecordRef->id : kDNSRecordIndexDefaultTXT, inFlags, inRDataSize, inRData, inTTL );
751 require_noerr( err, exit );
752
753 exit:
754 RMxUnlock();
755 return( err );
756 }
757
758 //===========================================================================================================================
759 // DNSServiceRemoveRecord_client
760 //===========================================================================================================================
761
762 DNSServiceErrorType DNSServiceRemoveRecord_client( DNSServiceRef inRef, DNSRecordRef inRecordRef, DNSServiceFlags inFlags )
763 {
764 DNSServiceErrorType err;
765
766 RMxLock();
767 dlog( kDebugLevelTrace, "\n" DEBUG_NAME "RemoveRecord flags=0x%08X\n", inFlags );
768 require_action( inRef, exit, err = kDNSServiceErr_BadReference );
769 require_action( inRef->session, exit, err = kDNSServiceErr_NotInitialized );
770 require_action( inRecordRef, exit, err = kDNSServiceErr_BadReference );
771 require_action( inFlags == 0, exit, err = kDNSServiceErr_BadFlags );
772
773 err = RMxSessionSendMessage( inRef->session, kRMxOpCodeRemoveRecord, kNoErr, "ww", inRecordRef->id, inFlags );
774 DNSServiceConnectionRecordRemove_client( inRef, inRecordRef );
775 free( inRecordRef );
776 require_noerr( err, exit );
777
778 exit:
779 RMxUnlock();
780 return( err );
781 }
782
783 #if 0
784 #pragma mark -
785 #pragma mark == DNS-SD Service Discovery ==
786 #endif
787
788 //===========================================================================================================================
789 // DNSServiceBrowse_direct
790 //===========================================================================================================================
791
792 DNSServiceErrorType
793 DNSServiceBrowse_client(
794 DNSServiceRef * outRef,
795 const char * inServer,
796 DNSServiceFlags inFlags,
797 uint32_t inInterfaceIndex,
798 const char * inType,
799 const char * inDomain,
800 DNSServiceBrowseReply inCallBack,
801 void * inContext )
802 {
803 DNSServiceErrorType err;
804 DNSServiceRef obj;
805
806 obj = NULL;
807 dlog( kDebugLevelTrace, "\n" DEBUG_NAME "Browse flags=0x%08X, ifi=%d, type=\"%s\", domain=\"%s\"\n",
808 inFlags, inInterfaceIndex, inType, inDomain ? inDomain : "<default>" );
809 require_action( outRef, exit, err = kDNSServiceErr_BadReference );
810 require_action( inFlags == 0, exit, err = kDNSServiceErr_BadFlags );
811 require_action( inType, exit, err = kDNSServiceErr_BadParam );
812 require_action( inCallBack, exit, err = kDNSServiceErr_BadParam );
813
814 obj = (DNSServiceRef) calloc( 1, sizeof( *obj ) );
815 require_action( obj, exit, err = kDNSServiceErr_NoMemory );
816
817 obj->context = inContext;
818 obj->u.browse.callback = inCallBack;
819
820 // Open a session to the server and send the request.
821
822 err = RMxSessionOpen( inServer, kRMxSessionFlagsNoClose, kInvalidSocketRef, RMxClientMessageCallBack, obj,
823 &obj->session, kRMxOpCodeBrowse, "wwss", inFlags, inInterfaceIndex, inType, inDomain ? inDomain : "" );
824 require_noerr( err, exit );
825
826 // Success!
827
828 *outRef = obj;
829 obj = NULL;
830
831 exit:
832 if( obj )
833 {
834 DNSServiceRefDeallocate_client( obj );
835 }
836 return( err );
837 }
838
839 //===========================================================================================================================
840 // DNSServiceBrowseReply_client
841 //===========================================================================================================================
842
843 DEBUG_LOCAL void DNSServiceBrowseReply_client( RMxMessage *inMessage )
844 {
845 OSStatus err;
846 DNSServiceRef obj;
847 DNSServiceFlags flags;
848 uint32_t interfaceIndex;
849 DNSServiceErrorType errorCode;
850 const char * name;
851 const char * type;
852 const char * domain;
853
854 check( inMessage );
855 obj = (DNSServiceRef) inMessage->context;
856 check( obj );
857
858 err = inMessage->status;
859 if( err == kNoErr )
860 {
861 err = RMxUnpack( inMessage->recvData, inMessage->recvSize, "wwwsss",
862 &flags, &interfaceIndex, &errorCode, &name, NULL, &type, NULL, &domain, NULL );
863 check_noerr( err );
864 if( err == kNoErr )
865 {
866 dlog( kDebugLevelTrace, DEBUG_NAME
867 "Browse reply flags=0x%08X, ifi=%d, err=%d, name=\"%s\", type=\"%s\", domain=\"%s\"\n",
868 flags, interfaceIndex, errorCode, name, type, domain );
869
870 obj->u.browse.callback( obj, flags, interfaceIndex, errorCode, name, type, domain, obj->context );
871 }
872 }
873 if( err != kNoErr )
874 {
875 obj->u.browse.callback( obj, 0, 0, err, "", "", "", obj->context );
876 }
877 }
878
879 #if 0
880 #pragma mark -
881 #endif
882
883 //===========================================================================================================================
884 // DNSServiceResolve_direct
885 //===========================================================================================================================
886
887 DNSServiceErrorType
888 DNSServiceResolve_client(
889 DNSServiceRef * outRef,
890 const char * inServer,
891 DNSServiceFlags inFlags,
892 uint32_t inInterfaceIndex,
893 const char * inName,
894 const char * inType,
895 const char * inDomain,
896 DNSServiceResolveReply inCallBack,
897 void * inContext )
898 {
899 DNSServiceErrorType err;
900 DNSServiceRef obj;
901
902 obj = NULL;
903 dlog( kDebugLevelTrace, "\n" DEBUG_NAME "Resolve flags=0x%08X, ifi=%d, name=\"%s\", type=\"%s\", domain=\"%s\"\n",
904 inFlags, inInterfaceIndex, inName, inType, inDomain ? inDomain : "<default>" );
905 require_action( outRef, exit, err = kDNSServiceErr_BadReference );
906 require_action( inFlags == 0, exit, err = kDNSServiceErr_BadFlags );
907 require_action( inName, exit, err = kDNSServiceErr_BadParam );
908 require_action( inType, exit, err = kDNSServiceErr_BadParam );
909 require_action( inCallBack, exit, err = kDNSServiceErr_BadParam );
910
911 obj = (DNSServiceRef) calloc( 1, sizeof( *obj ) );
912 require_action( obj, exit, err = kDNSServiceErr_NoMemory );
913
914 obj->context = inContext;
915 obj->u.resolve.flags = inFlags;
916 obj->u.resolve.callback = inCallBack;
917
918 // Open a session to the server and send the request.
919
920 err = RMxSessionOpen( inServer, kRMxSessionFlagsNoClose, kInvalidSocketRef, RMxClientMessageCallBack, obj,
921 &obj->session, kRMxOpCodeResolve, "wwsss", inFlags, inInterfaceIndex, inName, inType, inDomain ? inDomain : "" );
922 require_noerr( err, exit );
923
924 // Success!
925
926 *outRef = obj;
927 obj = NULL;
928
929 exit:
930 if( obj )
931 {
932 DNSServiceRefDeallocate_client( obj );
933 }
934 return( err );
935 }
936
937 //===========================================================================================================================
938 // DNSServiceResolveReply_client
939 //===========================================================================================================================
940
941 DEBUG_LOCAL void DNSServiceResolveReply_client( RMxMessage *inMessage )
942 {
943 OSStatus err;
944 DNSServiceRef obj;
945 DNSServiceFlags flags;
946 uint32_t interfaceIndex;
947 DNSServiceErrorType errorCode;
948 const char * name;
949 const char * host;
950 uint16_t port;
951 const char * txt;
952 size_t txtSize;
953
954 check( inMessage );
955 obj = (DNSServiceRef) inMessage->context;
956 check( obj );
957
958 err = inMessage->status;
959 if( err == kNoErr )
960 {
961 err = RMxUnpack( inMessage->recvData, inMessage->recvSize, "wwwsshn",
962 &flags, &interfaceIndex, &errorCode, &name, NULL, &host, NULL, &port, &txt, &txtSize );
963 check_noerr( err );
964 if( err == kNoErr )
965 {
966 dlog( kDebugLevelTrace, DEBUG_NAME
967 "Resolve reply flags=0x%08X, ifi=%d, err=%d, name=\"%s\", host=\"%s\", port=%d, txtSize=%d\n",
968 flags, interfaceIndex, errorCode, name, host, ntohs( port ), (int) txtSize );
969
970 obj->u.resolve.callback( obj, flags, interfaceIndex, errorCode, name, host, port, (uint16_t) txtSize, txt,
971 obj->context );
972 }
973 }
974 if( err != kNoErr )
975 {
976 obj->u.resolve.callback( obj, 0, 0, err, "", "", 0, 0, NULL, obj->context );
977 }
978 }
979
980 #if 0
981 #pragma mark -
982 #pragma mark == DNS-SD Special Purpose ==
983 #endif
984
985 //===========================================================================================================================
986 // DNSServiceCreateConnection_client
987 //===========================================================================================================================
988
989 DNSServiceErrorType DNSServiceCreateConnection_client( DNSServiceRef *outRef, const char *inServer )
990 {
991 DNSServiceErrorType err;
992 DNSServiceRef obj;
993
994 obj = NULL;
995 dlog( kDebugLevelTrace, "\n" DEBUG_NAME "CreateConnection (server=\"%s\")\n", inServer ? inServer : "<local>" );
996 require_action( outRef, exit, err = kDNSServiceErr_BadReference );
997
998 obj = (DNSServiceRef) calloc( 1, sizeof( *obj ) );
999 require_action( obj, exit, err = kDNSServiceErr_NoMemory );
1000
1001 err = RMxSessionOpen( inServer, kRMxSessionFlagsNoClose, kInvalidSocketRef, RMxClientMessageCallBack, obj,
1002 &obj->session, kRMxOpCodeCreateConnection, "" );
1003 require_noerr( err, exit );
1004
1005 *outRef = obj;
1006 obj = NULL;
1007
1008 exit:
1009 if( obj )
1010 {
1011 DNSServiceRefDeallocate_client( obj );
1012 }
1013 return( err );
1014 }
1015
1016 //===========================================================================================================================
1017 // DNSServiceConnectionRecordRemove_client
1018 //
1019 // Warning: Assumes the RMx lock is held (or is not needed due to a single thread having exclusive access).
1020 //===========================================================================================================================
1021
1022 DEBUG_LOCAL DNSRecordRef DNSServiceConnectionRecordRemove_client( DNSServiceRef inRef, DNSRecordRef inRecordRef )
1023 {
1024 DNSRecordRef * p;
1025
1026 for( p = &inRef->records; *p; p = &( *p )->next )
1027 {
1028 if( *p == inRecordRef )
1029 {
1030 break;
1031 }
1032 }
1033 inRecordRef = *p;
1034 if( inRecordRef )
1035 {
1036 *p = inRecordRef->next;
1037 }
1038 return( inRecordRef );
1039 }
1040
1041 //===========================================================================================================================
1042 // DNSServiceRegisterRecord_client
1043 //===========================================================================================================================
1044
1045 DNSServiceErrorType
1046 DNSServiceRegisterRecord_client(
1047 DNSServiceRef inRef,
1048 DNSRecordRef * outRecordRef,
1049 DNSServiceFlags inFlags,
1050 uint32_t inInterfaceIndex,
1051 const char * inName,
1052 uint16_t inRRType,
1053 uint16_t inRRClass,
1054 uint16_t inRDataSize,
1055 const void * inRData,
1056 uint32_t inTTL,
1057 DNSServiceRegisterRecordReply inCallBack,
1058 void * inContext )
1059 {
1060 DNSServiceErrorType err;
1061 DNSRecordRef obj;
1062
1063 DEBUG_UNUSED( inContext );
1064
1065 obj = NULL;
1066 RMxLock();
1067 dlog( kDebugLevelTrace, "\n" DEBUG_NAME
1068 "RegisterRecord flags=0x%08X, ifi=%d, name=\"%s\" rrType=0x%04X, rrClass=0x%04X, rDataSize=%d, ttl=%d\n",
1069 inFlags, inInterfaceIndex, inName, inRRType, inRRClass, inRDataSize, inTTL );
1070 require_action( inRef, exit, err = kDNSServiceErr_BadReference );
1071 require_action( inRef->session, exit, err = kDNSServiceErr_NotInitialized );
1072 require_action( outRecordRef, exit, err = kDNSServiceErr_BadParam );
1073 require_action( ( inFlags == kDNSServiceFlagsShared ) || ( inFlags == kDNSServiceFlagsUnique ),
1074 exit, err = kDNSServiceErr_BadFlags );
1075 require_action( inName, exit, err = kDNSServiceErr_BadParam );
1076 require_action( inRData && ( inRDataSize > 0 ), exit, err = kDNSServiceErr_BadParam );
1077 require_action( inCallBack, exit, err = kDNSServiceErr_BadFlags );
1078
1079 // Allocate and initialize the object.
1080
1081 obj = (DNSRecordRef) calloc( 1, sizeof( *obj ) );
1082 require_action( obj, exit, err = kDNSServiceErr_NoMemory );
1083
1084 obj->callback = inCallBack;
1085 obj->context = inContext;
1086
1087 // Set up a unique ID for the session, avoiding the reserved ID 0, add the record, then send the message.
1088
1089 obj->id = ++inRef->u.connection.lastID;
1090 if( obj->id == kDNSRecordIndexDefaultTXT )
1091 {
1092 obj->id = ++inRef->u.connection.lastID;
1093 }
1094 obj->next = inRef->records;
1095 inRef->records = obj;
1096
1097 err = RMxSessionSendMessage( inRef->session, kRMxOpCodeRegisterRecord, kNoErr, "wwwshhnw",
1098 obj->id, inFlags, inInterfaceIndex, inName, inRRType, inRRClass, inRDataSize, inRData, inTTL );
1099 require_noerr( err, exit );
1100
1101 // Success!
1102
1103 *outRecordRef = obj;
1104 obj = NULL;
1105
1106 exit:
1107 if( obj )
1108 {
1109 DNSServiceConnectionRecordRemove_client( inRef, obj );
1110 free( obj );
1111 }
1112 RMxUnlock();
1113 return( err );
1114 }
1115
1116 //===========================================================================================================================
1117 // DNSServiceRegisterRecordReply_client
1118 //===========================================================================================================================
1119
1120 DEBUG_LOCAL void DNSServiceRegisterRecordReply_client( RMxMessage *inMessage )
1121 {
1122 OSStatus err;
1123 DNSServiceRef obj;
1124 DNSServiceFlags flags;
1125 DNSServiceErrorType errorCode;
1126 uint32_t id;
1127 DNSRecordRef record;
1128
1129 check( inMessage );
1130 obj = (DNSServiceRef) inMessage->context;
1131 check( obj );
1132
1133 record = NULL;
1134 err = inMessage->status;
1135 if( err == kNoErr )
1136 {
1137 err = RMxUnpack( inMessage->recvData, inMessage->recvSize, "www", &flags, &errorCode, &id );
1138 check_noerr( err );
1139 if( err == kNoErr )
1140 {
1141 RMxLock();
1142 for( record = obj->records; record; record = record->next )
1143 {
1144 if( record->id == id )
1145 {
1146 break;
1147 }
1148 }
1149 RMxUnlock();
1150 if( !record )
1151 {
1152 dlog( kDebugLevelError, DEBUG_NAME "RegisterRecord reply with unknown record ID (%d)\n", id );
1153 err = kNotFoundErr;
1154 }
1155 if( err == kNoErr )
1156 {
1157 dlog( kDebugLevelTrace, DEBUG_NAME "RegisterRecord reply id=%d, flags=0x%08X, err=%d\n", id, flags, errorCode );
1158
1159 record->callback( obj, record, flags, errorCode, record->context );
1160 }
1161 }
1162 }
1163 if( err != kNoErr )
1164 {
1165 check( record );
1166 if( record )
1167 {
1168 record->callback( obj, NULL, 0, err, NULL );
1169 }
1170 }
1171 }
1172
1173 //===========================================================================================================================
1174 // DNSServiceQueryRecord_client
1175 //===========================================================================================================================
1176
1177 DNSServiceErrorType
1178 DNSServiceQueryRecord_client(
1179 DNSServiceRef * outRef,
1180 const char * inServer,
1181 DNSServiceFlags inFlags,
1182 uint32_t inInterfaceIndex,
1183 const char * inName,
1184 uint16_t inRRType,
1185 uint16_t inRRClass,
1186 DNSServiceQueryRecordReply inCallBack,
1187 void * inContext )
1188 {
1189 DNSServiceErrorType err;
1190 DNSServiceRef obj;
1191
1192 obj = NULL;
1193 dlog( kDebugLevelTrace, "\n" DEBUG_NAME "QueryRecord flags=0x%08X, ifi=%d, name=\"%s\", rrType=%d, rrClass=%d\n",
1194 inFlags, inInterfaceIndex, inName, inRRType, inRRClass );
1195 require_action( outRef, exit, err = kDNSServiceErr_BadReference );
1196 require_action( inFlags == 0, exit, err = kDNSServiceErr_BadFlags );
1197 require_action( inName, exit, err = kDNSServiceErr_BadParam );
1198 require_action( inCallBack, exit, err = kDNSServiceErr_BadFlags );
1199
1200 obj = (DNSServiceRef) calloc( 1, sizeof( *obj ) );
1201 require_action( obj, exit, err = kDNSServiceErr_NoMemory );
1202
1203 obj->context = inContext;
1204 obj->u.query.callback = inCallBack;
1205
1206 // Open a session to the server and send the request.
1207
1208 err = RMxSessionOpen( inServer, kRMxSessionFlagsNoClose, kInvalidSocketRef, RMxClientMessageCallBack, obj,
1209 &obj->session, kRMxOpCodeQueryRecord, "wwshh", inFlags, inInterfaceIndex, inName, inRRType, inRRClass );
1210 require_noerr( err, exit );
1211
1212 // Success!
1213
1214 *outRef = obj;
1215 obj = NULL;
1216
1217 exit:
1218 if( obj )
1219 {
1220 DNSServiceRefDeallocate_client( obj );
1221 }
1222 return( err );
1223 }
1224
1225 //===========================================================================================================================
1226 // DNSServiceQueryRecordReply_client
1227 //===========================================================================================================================
1228
1229 DEBUG_LOCAL void DNSServiceQueryRecordReply_client( RMxMessage *inMessage )
1230 {
1231 OSStatus err;
1232 DNSServiceRef obj;
1233 DNSServiceFlags flags;
1234 uint32_t interfaceIndex;
1235 DNSServiceErrorType errorCode;
1236 const char * name;
1237 uint16_t rrType;
1238 uint16_t rrClass;
1239 uint8_t * rData;
1240 size_t rDataSize;
1241 uint32_t ttl;
1242
1243 check( inMessage );
1244 obj = (DNSServiceRef) inMessage->context;
1245 check( obj );
1246
1247 err = inMessage->status;
1248 if( err == kNoErr )
1249 {
1250 err = RMxUnpack( inMessage->recvData, inMessage->recvSize, "wwwshhnw",
1251 &flags, &interfaceIndex, &errorCode, &name, NULL, &rrType, &rrClass, &rData, &rDataSize, &ttl );
1252 check_noerr( err );
1253 if( err == kNoErr )
1254 {
1255 dlog( kDebugLevelTrace, DEBUG_NAME
1256 "QueryRecord reply flags=0x%08X, ifi=%d, err=%d, name=\"%s\", rrType=%d, rrClass=%d, rDataSize=%d, ttl=%d\n",
1257 flags, interfaceIndex, errorCode, name, rrType, rrClass, rDataSize, ttl );
1258
1259 obj->u.query.callback( obj, flags, interfaceIndex, errorCode, name, rrType, rrClass, (uint16_t) rDataSize, rData,
1260 ttl, obj->context );
1261 }
1262 }
1263 if( err != kNoErr )
1264 {
1265 obj->u.query.callback( obj, 0, 0, err, "", 0, 0, 0, NULL, 0, obj->context );
1266 }
1267 }
1268
1269 //===========================================================================================================================
1270 // DNSServiceReconfirmRecord_client
1271 //===========================================================================================================================
1272
1273 void
1274 DNSServiceReconfirmRecord_client(
1275 const char * inServer,
1276 DNSServiceFlags inFlags,
1277 uint32_t inInterfaceIndex,
1278 const char * inName,
1279 uint16_t inRRType,
1280 uint16_t inRRClass,
1281 uint16_t inRDataSize,
1282 const void * inRData )
1283 {
1284 DNSServiceErrorType err;
1285
1286 dlog( kDebugLevelTrace, "\n" DEBUG_NAME "ReconfirmRecord flags=0x%08X, ifi=%d, name=\"%s\", rrType=%d, rrClass=%d\n",
1287 inFlags, inInterfaceIndex, inName, inRRType, inRRClass );
1288 require_action( inFlags == 0, exit, err = kDNSServiceErr_BadFlags );
1289 require_action( inName, exit, err = kDNSServiceErr_BadParam );
1290 require_action( inRData && ( inRDataSize > 0 ), exit, err = kDNSServiceErr_BadParam );
1291
1292 err = RMxSessionOpen( inServer, kRMxSessionFlagsNoClose, kInvalidSocketRef, NULL, NULL, NULL,
1293 kRMxOpCodeReconfirmRecord, "wwshhn", inFlags, inInterfaceIndex, inName, inRRType, inRRClass, inRDataSize, inRData );
1294 require_noerr( err, exit );
1295
1296 exit:
1297 return;
1298 }
1299
1300 #ifdef __cplusplus
1301 }
1302 #endif