2 * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
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
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.
23 * @APPLE_LICENSE_HEADER_END@
25 Change History (most recent first):
28 Revision 1.6 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.
32 Revision 1.5 2004/04/09 21:03:14 bradley
33 Changed port numbers to use network byte order for consistency with other platforms.
35 Revision 1.4 2004/04/08 21:14:19 bradley
36 Changed resolve callback to use correct calling conventions (previously hidden by a cast).
38 Revision 1.3 2004/04/08 09:43:43 bradley
39 Changed callback calling conventions to __stdcall so they can be used with C# delegates.
41 Revision 1.2 2004/03/16 22:09:03 bradley
42 Skip socket creation failures to handle local IPv6 addresses being returned by Windows even when
43 they are not actually supported by the OS; Log a message and only fail if no sockets can be created.
45 Revision 1.1 2004/01/30 02:35:13 bradley
46 Rendezvous Message Exchange implementation for DNS-SD IPC on Windows.
54 #include "CommonServices.h"
55 #include "DebugServices.h"
58 #include "DNSSDDirect.h"
59 #include "RMxCommon.h"
61 #include "RMxServer.h"
68 #pragma mark == Constants ==
71 //===========================================================================================================================
73 //===========================================================================================================================
75 #define DEBUG_NAME "[RMxServer] "
78 #pragma mark == Structures ==
81 //===========================================================================================================================
83 //===========================================================================================================================
85 typedef void ( *DNSServiceRefReleaseCallBack
)( DNSServiceRef inRef
);
89 typedef struct _DNSServiceRef_t _DNSServiceRef_t
;
90 struct _DNSServiceRef_t
94 RMxSessionRef session
;
95 DNSServiceRef directObj
;
101 typedef struct _DNSRecordRef_t _DNSRecordRef_t
;
102 struct _DNSRecordRef_t
107 DNSRecordRef directObj
;
111 #pragma mark == Prototypes ==
114 //===========================================================================================================================
116 //===========================================================================================================================
120 DEBUG_LOCAL OSStatus
RMxServerRunInitialize( void );
121 DEBUG_LOCAL
void RMxServerRunFinalize( void );
122 DEBUG_LOCAL
void RMxServerMessageCallBack( RMxMessage
*inMessage
);
126 DEBUG_LOCAL
void DNSServiceRefDeallocate_server( DNSServiceRef inRef
);
127 DEBUG_LOCAL
void DNSServiceCheckVersion_server( RMxMessage
*inMessage
);
131 DEBUG_LOCAL
void DNSServiceCopyProperty_server( RMxMessage
*inMessage
);
132 DEBUG_LOCAL OSStatus
DNSServiceCopyPropertySendData_server( DNSPropertyCode inCode
, RMxMessage
*inMessage
);
134 // Domain Enumeration
136 DEBUG_LOCAL
void DNSServiceEnumerateDomains_server( RMxMessage
*inMessage
);
137 DEBUG_LOCAL
void CALLBACK_COMPAT
138 DNSServiceEnumerateDomainsCallBack_server(
140 DNSServiceFlags flags
,
141 uint32_t interfaceIndex
,
142 DNSServiceErrorType errorCode
,
143 const char * replyDomain
,
146 // Service Registration
148 DEBUG_LOCAL
void DNSServiceRegister_server( RMxMessage
*inMessage
);
149 DEBUG_LOCAL
void CALLBACK_COMPAT
150 DNSServiceRegisterCallBack_server(
152 DNSServiceFlags inFlags
,
153 DNSServiceErrorType inErrorCode
,
156 const char * inDomain
,
159 DEBUG_LOCAL
void DNSServiceAddRecord_server( RMxMessage
*inMessage
);
160 DEBUG_LOCAL
void DNSServiceUpdateRecord_server( RMxMessage
*inMessage
);
161 DEBUG_LOCAL
void DNSServiceRemoveRecord_server( RMxMessage
*inMessage
);
165 DEBUG_LOCAL
void DNSServiceBrowse_server( RMxMessage
*inMessage
);
166 DEBUG_LOCAL
void CALLBACK_COMPAT
167 DNSServiceBrowseCallBack_server(
169 DNSServiceFlags inFlags
,
170 uint32_t inInterfaceIndex
,
171 DNSServiceErrorType inErrorCode
,
174 const char * inDomain
,
177 DEBUG_LOCAL
void DNSServiceResolve_server( RMxMessage
*inMessage
);
178 DEBUG_LOCAL
void CALLBACK_COMPAT
179 DNSServiceResolveCallBack_server(
181 DNSServiceFlags inFlags
,
182 uint32_t inInterfaceIndex
,
183 DNSServiceErrorType inErrorCode
,
184 const char * inFullName
,
185 const char * inHostName
,
193 DEBUG_LOCAL
void DNSServiceCreateConnection_server( RMxMessage
*inMessage
);
195 DEBUG_LOCAL
void DNSServiceRegisterRecord_server( RMxMessage
*inMessage
);
196 DEBUG_LOCAL
void CALLBACK_COMPAT
197 DNSServiceRegisterRecordCallBack_server(
199 DNSRecordRef inRecordRef
,
200 DNSServiceFlags inFlags
,
201 DNSServiceErrorType inErrorCode
,
204 DEBUG_LOCAL
void DNSServiceQueryRecord_server( RMxMessage
*inMessage
);
205 DEBUG_LOCAL
void CALLBACK_COMPAT
206 DNSServiceQueryRecordCallBack_server(
208 DNSServiceFlags inFlags
,
209 uint32_t inInterfaceIndex
,
210 DNSServiceErrorType inErrorCode
,
214 uint16_t inRDataSize
,
215 const void * inRData
,
219 DEBUG_LOCAL
void DNSServiceReconfirmRecord_server( RMxMessage
*inMessage
);
222 #pragma mark == Globals ==
225 //===========================================================================================================================
227 //===========================================================================================================================
229 DEBUG_LOCAL RMxServerFlags gRMxServerFlags
= kRMxServerFlagsNone
;
230 DEBUG_LOCAL SocketRef gRMxServerSockets
[ 2 ] = { kInvalidSocketRef
, kInvalidSocketRef
};
231 DEBUG_LOCAL HANDLE gRMxServerSocketEvents
[ 2 ] = { NULL
, NULL
};
232 DEBUG_LOCAL HANDLE gRMxServerQuitDoneEvent
= NULL
;
236 #pragma mark == RMx ==
239 //===========================================================================================================================
240 // RMxServerInitialize
241 //===========================================================================================================================
243 OSStatus
RMxServerInitialize( RMxServerFlags inFlags
)
247 err
= RMxInitialize();
248 require_noerr( err
, exit
);
250 // Set up the quit done event to allow for waiting until the run loop is quit. A manual-reset event is used so
251 // multiple calls to the stopping code will all see that the quit event has been signaled (not just the first).
252 // The event is also created as signaled so even if run is not called, a stop or finalize will still run successfully.
253 // The event will be explicitly reset to an unsignaled state when the run loop starts.
255 gRMxServerQuitDoneEvent
= CreateEvent( NULL
, TRUE
, FALSE
, NULL
);
256 err
= translate_errno( gRMxServerQuitDoneEvent
, errno_compat(), kNoResourcesErr
);
257 require_noerr( err
, exit
);
259 gRMxServerFlags
= inFlags
;
265 //===========================================================================================================================
267 //===========================================================================================================================
269 void RMxServerFinalize( void )
273 RMxServerStop( kRMxServerStopFlagsNone
);
275 // Release the quit event.
277 if( gRMxServerQuitDoneEvent
)
279 ok
= CloseHandle( gRMxServerQuitDoneEvent
);
280 check_translated_errno( ok
, errno_compat(), kUnknownErr
);
281 gRMxServerQuitDoneEvent
= NULL
;
287 //===========================================================================================================================
289 //===========================================================================================================================
291 OSStatus
RMxServerRun( void )
295 HANDLE waitHandles
[ 3 ];
297 // Initialize the server run loop and set up the list of objects to wait for.
299 err
= RMxServerRunInitialize();
300 require_noerr( err
, exit
);
303 waitHandles
[ waitCount
++ ] = gRMxServerSocketEvents
[ 0 ];
304 waitHandles
[ waitCount
++ ] = gRMxServerSocketEvents
[ 1 ];
305 waitHandles
[ waitCount
++ ] = gRMxStateChangeEvent
;
306 check( waitCount
== sizeof_array( waitHandles
) );
308 // Main event loop. Process connection requests and state changes (i.e. quit).
310 while( gRMxState
== kRMxStateRun
)
314 result
= WaitForMultipleObjects( waitCount
, waitHandles
, FALSE
, INFINITE
);
315 if( ( result
== WAIT_OBJECT_0
) ||
316 ( result
== ( WAIT_OBJECT_0
+ 1 ) ) ) // Socket Events
319 struct sockaddr_storage addr
;
323 index
= result
- WAIT_OBJECT_0
;
324 check( ( index
== 0 ) || IsValidSocket( gRMxServerSockets
[ index
] ) );
326 // The socket event is only set up to notify on connection requests so try to accept the connection.
327 // Note: It is possible for accept to fail if the client aborts the connection after the network stack
328 // sees the connection request, but before accept is called. See UNPv1 section 15.6 for more information.
330 addrSize
= sizeof( addr
);
331 sock
= accept( gRMxServerSockets
[ index
], (struct sockaddr
*) &addr
, &addrSize
);
332 if( IsValidSocket( sock
) )
334 if( ( gRMxServerFlags
& kRMxServerFlagsAllowRemote
) || SOCKADDR_IS_IP_LOOPBACK( &addr
) )
336 dlog( kDebugLevelNotice
, "\n" DEBUG_NAME
"accepting connection from %##a\n", &addr
);
338 err
= RMxSessionOpen( NULL
, kRMxSessionFlagsNone
, sock
, RMxServerMessageCallBack
, NULL
, NULL
,
339 kRMxOpCodeInvalid
, NULL
);
344 dlog( kDebugLevelNotice
, DEBUG_NAME
"remote connection attempt from %##a when local-only\n", &addr
);
346 err
= close_compat( sock
);
347 check_translated_errno( err
== 0, errno_compat(), kUnknownErr
);
352 err
= errno_compat();
353 dlog( kDebugLevelWarning
, DEBUG_NAME
"connection abort before accept (%d %m)\n", err
, err
);
356 else if( result
== ( WAIT_OBJECT_0
+ 2 ) ) // State Change Event
358 dlog( kDebugLevelNotice
, DEBUG_NAME
"state change (%d)\n", gRMxState
);
363 err
= (OSStatus
) GetLastError();
364 dlog( kDebugLevelAlert
, DEBUG_NAME
"wait error: 0x%08X, %d (%m)\n", result
, err
, err
);
365 err
= (OSStatus
) result
;
372 RMxServerRunFinalize();
376 //===========================================================================================================================
377 // RMxServerRunInitialize
378 //===========================================================================================================================
380 DEBUG_LOCAL OSStatus
RMxServerRunInitialize( void )
383 struct addrinfo hints
;
384 struct addrinfo
* addrList
;
385 struct addrinfo
* addr
;
392 // Set up a socket for each address (only expected to be a single IPv4 and optionally a single IPv6 address).
393 // Windows does not support IPv4-mapped IPv6 addresses so we have to create a separate socket for each type.
395 memset( &hints
, 0, sizeof( hints
) );
396 hints
.ai_flags
= AI_PASSIVE
;
397 hints
.ai_family
= AF_UNSPEC
;
398 hints
.ai_socktype
= SOCK_STREAM
;
399 hints
.ai_protocol
= IPPROTO_TCP
;
401 err
= getaddrinfo( NULL
, kRMxServerPortString
, &hints
, &addrList
);
402 require_noerr( err
, exit
);
405 for( addr
= addrList
; addr
; addr
= addr
->ai_next
)
407 dlog( kDebugLevelTrace
, DEBUG_NAME
"setting up %s socket\n",
408 ( addr
->ai_family
== AF_INET
) ? "AF_INET" : ( addr
->ai_family
== AF_INET6
) ? "AF_INET6" : "<unknown>" );
411 dlog( kDebugLevelWarning
, DEBUG_NAME
"cannot handle more than 2 listening sockets (unexpected)\n" );
415 gRMxServerSockets
[ nAddrs
] = socket( addr
->ai_family
, addr
->ai_socktype
, addr
->ai_protocol
);
416 err
= translate_errno( IsValidSocket( gRMxServerSockets
[ nAddrs
] ), errno_compat(), kNoResourcesErr
);
419 dlog( kDebugLevelNotice
, DEBUG_NAME
"%s socket not supported (%d %m)\n",
420 ( addr
->ai_family
== AF_INET
) ? "AF_INET" : ( addr
->ai_family
== AF_INET6
) ? "AF_INET6" : "<unknown>",
425 // Enable the address-reuse option so the server can be stopped and re-started without the TIME_WAIT delay.
428 err
= setsockopt( gRMxServerSockets
[ nAddrs
], SOL_SOCKET
, SO_REUSEADDR
, (char *) &option
, sizeof( option
) );
429 err
= translate_errno( err
== 0, errno_compat(), kInUseErr
);
430 require_noerr( err
, exit
);
432 // Set up to signal an event when a connection can be accepted so we can wait for it with WaitForMultipleObjects.
433 // Note: WSAEventSelect makes the socket non-blocking so it does not need to made non-blocking separately.
435 gRMxServerSocketEvents
[ nAddrs
] = CreateEvent( NULL
, FALSE
, FALSE
, NULL
);
436 err
= translate_errno( gRMxServerSocketEvents
[ nAddrs
], errno_compat(), kNoResourcesErr
);
437 require_noerr( err
, exit
);
439 err
= WSAEventSelect( gRMxServerSockets
[ nAddrs
], gRMxServerSocketEvents
[ nAddrs
], FD_ACCEPT
);
440 err
= translate_errno( err
== 0, errno_compat(), kInUseErr
);
441 require_noerr( err
, exit
);
443 // Bind to the server port and enable listening for connections.
445 err
= bind( gRMxServerSockets
[ nAddrs
], addr
->ai_addr
, (int) addr
->ai_addrlen
);
446 err
= translate_errno( err
== 0, errno_compat(), kNoResourcesErr
);
447 require_noerr( err
, exit
);
449 err
= listen( gRMxServerSockets
[ nAddrs
], SOMAXCONN
);
450 err
= translate_errno( err
== 0, errno_compat(), kNoResourcesErr
);
451 require_noerr( err
, exit
);
455 require_action( nAddrs
> 0, exit
, err
= kUnknownErr
);
457 // Create a dummy event (which will never be signaled) to simplify WaitForMultipleObjects usage,
459 if( !gRMxServerSocketEvents
[ 1 ] )
461 gRMxServerSocketEvents
[ 1 ] = CreateEvent( NULL
, FALSE
, FALSE
, NULL
);
462 err
= translate_errno( gRMxServerSocketEvents
[ 1 ], errno_compat(), kNoResourcesErr
);
463 require_noerr( err
, exit
);
466 // Reset the quit event to an unsignaled state so other code can wait for the run loop to quit.
468 gRMxState
= kRMxStateRun
;
469 ok
= ResetEvent( gRMxServerQuitDoneEvent
);
470 err
= translate_errno( ok
, errno_compat(), kUnknownErr
);
471 require_noerr( err
, exit
);
476 freeaddrinfo( addrList
);
480 RMxServerRunFinalize();
485 //===========================================================================================================================
486 // RMxServerRunFinalize
488 // Note: This routine is safe to call multiple times (for easier cleanup).
489 //===========================================================================================================================
491 DEBUG_LOCAL
void RMxServerRunFinalize( void )
496 // Release the socket events
498 if( gRMxServerSocketEvents
[ 0 ] )
500 ok
= CloseHandle( gRMxServerSocketEvents
[ 0 ] );
501 check_translated_errno( ok
, errno_compat(), kUnknownErr
);
502 gRMxServerSocketEvents
[ 0 ] = NULL
;
504 if( gRMxServerSocketEvents
[ 1 ] )
506 ok
= CloseHandle( gRMxServerSocketEvents
[ 1 ] );
507 check_translated_errno( ok
, errno_compat(), kUnknownErr
);
508 gRMxServerSocketEvents
[ 1 ] = NULL
;
511 // Close the sockets.
513 if( IsValidSocket( gRMxServerSockets
[ 0 ] ) )
515 err
= close_compat( gRMxServerSockets
[ 0 ] );
516 check_translated_errno( err
== 0, errno_compat(), kUnknownErr
);
517 gRMxServerSockets
[ 0 ] = kInvalidSocketRef
;
519 if( IsValidSocket( gRMxServerSockets
[ 1 ] ) )
521 err
= close_compat( gRMxServerSockets
[ 1 ] );
522 check_translated_errno( err
== 0, errno_compat(), kUnknownErr
);
523 gRMxServerSockets
[ 1 ] = kInvalidSocketRef
;
526 // Signal the quit event to indicate the run loop has quit.
528 ok
= SetEvent( gRMxServerQuitDoneEvent
);
529 check_translated_errno( ok
, errno_compat(), kUnknownErr
);
532 //===========================================================================================================================
534 //===========================================================================================================================
536 OSStatus
RMxServerStop( RMxServerStopFlags inFlags
)
541 // Signal a state changed event to trigger everything to stop. Note: This is a manual-reset event so it will
542 // remain signaled to allow all running threads to wake up and exit cleanly.
544 gRMxState
= kRMxStateStop
;
545 if( gRMxStateChangeEvent
)
547 ok
= SetEvent( gRMxStateChangeEvent
);
548 check_translated_errno( ok
, errno_compat(), kUnknownErr
);
551 // Wait for the quit event indicating the run loop has quit. Give up after 10 seconds to handle a hung thread.
553 if( !( inFlags
& kRMxServerStopFlagsNoWait
) )
555 if( gRMxServerQuitDoneEvent
)
557 result
= WaitForSingleObject( gRMxServerQuitDoneEvent
, 10 * 1000 );
558 check_translated_errno( result
== WAIT_OBJECT_0
, errno_compat(), result
);
565 //===========================================================================================================================
566 // RMxServerMessageCallBack
567 //===========================================================================================================================
569 DEBUG_LOCAL
void RMxServerMessageCallBack( RMxMessage
*inMessage
)
575 check( inMessage
->session
);
577 switch( inMessage
->opcode
)
581 case kRMxOpCodeInvalid
:
583 // The session is closing so delete the object (if still valid). Invalidate the session because the session
584 // is already in the process of closing so we don't want the deallocate code closing it again.
586 obj
= (DNSServiceRef
) inMessage
->context
;
589 obj
->sessionClosing
= true;
590 DNSServiceRefDeallocate_server( obj
);
594 case kRMxOpCodeCheckVersion
:
595 DNSServiceCheckVersion_server( inMessage
);
600 case kRMxOpCodeCopyProperty
:
601 DNSServiceCopyProperty_server( inMessage
);
604 // Domain Enumeration
606 case kRMxOpCodeEnumerateDomains
:
607 DNSServiceEnumerateDomains_server( inMessage
);
610 // Service Registration
612 case kRMxOpCodeRegister
:
613 DNSServiceRegister_server( inMessage
);
616 case kRMxOpCodeAddRecord
:
617 DNSServiceAddRecord_server( inMessage
);
620 case kRMxOpCodeUpdateRecord
:
621 DNSServiceUpdateRecord_server( inMessage
);
624 case kRMxOpCodeRemoveRecord
:
625 DNSServiceRemoveRecord_server( inMessage
);
630 case kRMxOpCodeBrowse
:
631 DNSServiceBrowse_server( inMessage
);
634 case kRMxOpCodeResolve
:
635 DNSServiceResolve_server( inMessage
);
640 case kRMxOpCodeCreateConnection
:
641 DNSServiceCreateConnection_server( inMessage
);
644 case kRMxOpCodeRegisterRecord
:
645 DNSServiceRegisterRecord_server( inMessage
);
648 case kRMxOpCodeQueryRecord
:
649 DNSServiceQueryRecord_server( inMessage
);
652 case kRMxOpCodeReconfirmRecord
:
653 DNSServiceReconfirmRecord_server( inMessage
);
657 dlog( kDebugLevelWarning
, DEBUG_NAME
"message with unknown opcode received (%d)\n", inMessage
->opcode
);
658 err
= RMxSessionSendMessage( inMessage
->session
, inMessage
->opcode
, kUnsupportedErr
, "" );
666 #pragma mark == DNS-SD General ==
669 //===========================================================================================================================
670 // DNSServiceRefDeallocate_server
671 //===========================================================================================================================
673 DEBUG_LOCAL
void DNSServiceRefDeallocate_server( DNSServiceRef inRef
)
679 dlog( kDebugLevelTrace
, DEBUG_NAME
"%s: ref=%#p\n", __ROUTINE__
, inRef
);
681 // Release the direct object if active.
683 if( inRef
->directObj
)
685 DNSServiceRefDeallocate_direct( inRef
->directObj
);
688 // Close the session.
690 if( inRef
->session
&& !inRef
->sessionClosing
)
692 inRef
->session
->callback
= NULL
;
693 inRef
->session
->message
.context
= NULL
;
695 err
= RMxSessionClose( inRef
->session
, kEndingErr
);
699 // Release any extra records.
701 while( inRef
->records
)
705 record
= inRef
->records
;
706 inRef
->records
= record
->next
;
711 // Release the object.
716 //===========================================================================================================================
717 // DNSServiceCheckVersion_server
718 //===========================================================================================================================
720 DEBUG_LOCAL
void DNSServiceCheckVersion_server( RMxMessage
*inMessage
)
723 uint32_t clientCurrentVersion
;
724 uint32_t clientOldestClientVersion
;
725 uint32_t clientOldestServerVersion
;
728 check( inMessage
->session
);
730 // Extract parameters from the message.
732 err
= RMxUnpack( inMessage
->recvData
, inMessage
->recvSize
, "www",
733 &clientCurrentVersion
, &clientOldestClientVersion
, &clientOldestServerVersion
);
734 require_noerr( err
, exit
);
736 dlog( kDebugLevelTrace
, DEBUG_NAME
"%s: clientCurrent=%v, clientOldestClient=%v, clientOldestServer=%v\n",
737 __ROUTINE__
, clientCurrentVersion
, clientOldestClientVersion
, clientOldestServerVersion
);
739 err
= RMxCheckVersion( clientCurrentVersion
, clientOldestClientVersion
, clientOldestServerVersion
,
740 kRMxCurrentVersion
, kRMxOldestClientVersion
, kRMxOldestServerVersion
);
742 // Send the response and our version information. Cause the session to quit since this is a one-shot session.
745 err
= RMxSessionSendMessage( inMessage
->session
, inMessage
->opcode
, kNoErr
, "wwww",
746 err
, kRMxCurrentVersion
, kRMxOldestClientVersion
, kRMxOldestServerVersion
);
749 inMessage
->session
->quit
= true;
754 #pragma mark == DNS-SD Properties ==
757 //===========================================================================================================================
758 // DNSServiceCopyProperty_server
759 //===========================================================================================================================
761 DEBUG_LOCAL
void DNSServiceCopyProperty_server( RMxMessage
*inMessage
)
764 DNSPropertyCode code
;
767 check( inMessage
->session
);
769 // Extract parameters from the message.
771 err
= RMxUnpack( inMessage
->recvData
, inMessage
->recvSize
, "w", &code
);
772 require_noerr( err
, exit
);
774 dlog( kDebugLevelTrace
, DEBUG_NAME
"%s: code='%C'\n", __ROUTINE__
, code
);
777 // Send the response and our version information. Cause the session to quit since this is a one-shot session.
780 err
= DNSServiceCopyPropertySendData_server( code
, inMessage
);
783 inMessage
->session
->quit
= true;
786 //===========================================================================================================================
787 // DNSServiceCopyPropertySendData_server
788 //===========================================================================================================================
790 DEBUG_LOCAL OSStatus
DNSServiceCopyPropertySendData_server( DNSPropertyCode inCode
, RMxMessage
*inMessage
)
796 case kDNSPropertyCodeVersion
:
798 // Note: This manually builds the "n" data type using a "w" size followed by the data to avoid a temporary buffer.
800 err
= RMxSessionSendMessage( inMessage
->session
, inMessage
->opcode
, kNoErr
, "ww wwww", kNoErr
, inCode
,
801 4 + 4 + 4, kRMxCurrentVersion
, kRMxOldestClientVersion
, kRMxOldestServerVersion
);
802 require_noerr( err
, exit
);
806 dlog( kDebugLevelWarning
, DEBUG_NAME
"%s: unknown property code (%C)\n", __ROUTINE__
, inCode
);
807 err
= kDNSServiceErr_Unsupported
;
808 err
= RMxSessionSendMessage( inMessage
->session
, inMessage
->opcode
, kNoErr
, "wn", err
, 0, NULL
);
809 require_noerr( err
, exit
);
819 #pragma mark DNSServiceReleaseProperty_server
822 // Note: DNSServiceReleaseProperty_server is not needed on the server side because memory is released immediately after sending.
826 #pragma mark == DNS-SD Domain Enumeration ==
829 //===========================================================================================================================
830 // DNSServiceEnumerateDomains_server
831 //===========================================================================================================================
833 DEBUG_LOCAL
void DNSServiceEnumerateDomains_server( RMxMessage
*inMessage
)
837 DNSServiceFlags flags
;
838 uint32_t interfaceIndex
;
842 check( inMessage
->session
);
843 require_action( !inMessage
->session
->message
.context
, exit
, err
= kTypeErr
);
845 // Extract parameters from the message.
847 err
= RMxUnpack( inMessage
->recvData
, inMessage
->recvSize
, "ww", &flags
, &interfaceIndex
);
848 require_noerr( err
, exit
);
850 dlog( kDebugLevelTrace
, DEBUG_NAME
"%s: flags=0x%08X, ifi=%d\n", __ROUTINE__
, flags
, interfaceIndex
);
852 // Allocate and initialize the object.
854 obj
= (DNSServiceRef
) calloc( 1, sizeof( *obj
) );
855 require_action( obj
, exit
, err
= kNoMemoryErr
);
857 obj
->opcode
= inMessage
->opcode
;
858 obj
->session
= inMessage
->session
;
860 err
= DNSServiceEnumerateDomains_direct( &obj
->directObj
, flags
, interfaceIndex
,
861 DNSServiceEnumerateDomainsCallBack_server
, obj
);
862 require_noerr( err
, exit
);
866 inMessage
->session
->message
.context
= obj
;
872 err
= RMxSessionSendMessage( inMessage
->session
, inMessage
->opcode
, err
, "" );
877 DNSServiceRefDeallocate_server( obj
);
881 //===========================================================================================================================
882 // DNSServiceEnumerateDomainsCallBack_server
883 //===========================================================================================================================
885 DEBUG_LOCAL
void CALLBACK_COMPAT
886 DNSServiceEnumerateDomainsCallBack_server(
888 DNSServiceFlags inFlags
,
889 uint32_t inInterfaceIndex
,
890 DNSServiceErrorType inErrorCode
,
891 const char * inDomain
,
897 DEBUG_UNUSED( inRef
);
900 obj
= (DNSServiceRef
) inContext
;
902 check( obj
->session
);
904 err
= RMxSessionSendMessage( obj
->session
, kRMxOpCodeEnumerateDomains
, kNoErr
, "wwws",
905 inFlags
, inInterfaceIndex
, inErrorCode
, inDomain
);
911 #pragma mark == DNS-SD Service Registration ==
914 //===========================================================================================================================
915 // DNSServiceRegister_server
916 //===========================================================================================================================
918 DEBUG_LOCAL
void DNSServiceRegister_server( RMxMessage
*inMessage
)
922 DNSServiceFlags flags
;
923 uint32_t interfaceIndex
;
934 check( inMessage
->session
);
935 require_action( !inMessage
->session
->message
.context
, exit
, err
= kTypeErr
);
937 // Extract parameters from the message.
939 err
= RMxUnpack( inMessage
->recvData
, inMessage
->recvSize
, "wwsssshn",
940 &flags
, &interfaceIndex
, &name
, NULL
, &type
, NULL
, &domain
, NULL
, &host
, NULL
, &port
, &txt
, &txtSize
);
941 require_noerr( err
, exit
);
943 dlog( kDebugLevelTrace
, DEBUG_NAME
944 "%s: flags=0x%08X, ifi=%ld, name=\"%s\", type=\"%s\", domain=\"%s\", host=\"%s\", port=%d, txtSize=%d\n",
945 __ROUTINE__
, flags
, interfaceIndex
, name
, type
, domain
, host
, ntohs( port
), txtSize
);
947 // Allocate and initialize the object.
949 obj
= (DNSServiceRef
) calloc( 1, sizeof( *obj
) );
950 require_action( obj
, exit
, err
= kNoMemoryErr
);
952 obj
->opcode
= inMessage
->opcode
;
953 obj
->session
= inMessage
->session
;
955 err
= DNSServiceRegister_direct( &obj
->directObj
, flags
, interfaceIndex
, name
, type
, domain
, host
, port
,
956 (uint16_t) txtSize
, txt
, DNSServiceRegisterCallBack_server
, obj
);
957 require_noerr( err
, exit
);
961 inMessage
->session
->message
.context
= obj
;
967 err
= RMxSessionSendMessage( inMessage
->session
, inMessage
->opcode
, err
, "" );
972 DNSServiceRefDeallocate_server( obj
);
976 //===========================================================================================================================
977 // DNSServiceRegisterCallBack_server
978 //===========================================================================================================================
980 DEBUG_LOCAL
void CALLBACK_COMPAT
981 DNSServiceRegisterCallBack_server(
983 DNSServiceFlags inFlags
,
984 DNSServiceErrorType inErrorCode
,
987 const char * inDomain
,
993 DEBUG_UNUSED( inRef
);
996 obj
= (DNSServiceRef
) inContext
;
998 check( obj
->session
);
1000 err
= RMxSessionSendMessage( obj
->session
, kRMxOpCodeRegister
, kNoErr
, "wwsss",
1001 inFlags
, inErrorCode
, inName
, inType
, inDomain
);
1005 //===========================================================================================================================
1006 // DNSServiceAddRecord_server
1007 //===========================================================================================================================
1009 DEBUG_LOCAL
void DNSServiceAddRecord_server( RMxMessage
*inMessage
)
1015 DNSServiceFlags flags
;
1024 check( inMessage
->session
);
1025 ref
= (DNSServiceRef
) inMessage
->context
;
1026 require_action( ref
, exit
, err
= kNotInitializedErr
);
1027 require_action( ref
->opcode
== kRMxOpCodeRegister
, exit
, err
= kTypeErr
);
1028 check( ref
->directObj
);
1030 // Extract parameters from the message.
1032 err
= RMxUnpack( inMessage
->recvData
, inMessage
->recvSize
, "wwhnw", &id
, &flags
, &rrType
, &rData
, &rDataSize
, &ttl
);
1033 require_noerr( err
, exit
);
1035 dlog( kDebugLevelTrace
, DEBUG_NAME
"%s: id=%d, flags=0x%08X, rrType=%d, rDataSize=%d, ttl=%d\n",
1036 __ROUTINE__
, id
, flags
, rrType
, rDataSize
, ttl
);
1038 // Allocate and initialize the object and add it to the list of records.
1040 obj
= (DNSRecordRef
) calloc( 1, sizeof( *obj
) );
1041 require_action( obj
, exit
, err
= kNoMemoryErr
);
1045 obj
->next
= ref
->records
;
1048 err
= DNSServiceAddRecord_direct( ref
->directObj
, &obj
->directObj
, flags
, rrType
, (uint16_t) rDataSize
, rData
, ttl
);
1049 require_noerr( err
, exit
);
1056 err
= RMxSessionSendMessage( inMessage
->session
, inMessage
->opcode
, err
, "" );
1061 for( p
= &ref
->records
; *p
; p
= &( *p
)->next
)
1073 //===========================================================================================================================
1074 // DNSServiceUpdateRecord_server
1075 //===========================================================================================================================
1077 DEBUG_LOCAL
void DNSServiceUpdateRecord_server( RMxMessage
*inMessage
)
1082 DNSServiceFlags flags
;
1089 check( inMessage
->session
);
1090 ref
= (DNSServiceRef
) inMessage
->context
;
1091 require_action( ref
, exit
, err
= kNotInitializedErr
);
1092 require_action( ( ref
->opcode
== kRMxOpCodeRegister
) || ( ref
->opcode
== kRMxOpCodeCreateConnection
), exit
, err
= kTypeErr
);
1093 check( ref
->directObj
);
1095 // Extract parameters from the message.
1097 err
= RMxUnpack( inMessage
->recvData
, inMessage
->recvSize
, "wwnw", &id
, &flags
, &rData
, &rDataSize
, &ttl
);
1098 require_noerr( err
, exit
);
1100 dlog( kDebugLevelTrace
, DEBUG_NAME
"%s: id=%d, flags=0x%08X, rDataSize=%d, ttl=%d\n", __ROUTINE__
, id
, flags
, rDataSize
, ttl
);
1102 // Find the record with the specified ID and update it.
1104 if( id
== kDNSRecordIndexDefaultTXT
)
1110 for( obj
= ref
->records
; obj
; obj
= obj
->next
)
1117 require_action( obj
, exit
, err
= kNotFoundErr
);
1118 check( obj
->directObj
);
1121 err
= DNSServiceUpdateRecord_direct( ref
->directObj
, obj
->directObj
, flags
, (uint16_t) rDataSize
, rData
, ttl
);
1122 require_noerr( err
, exit
);
1127 err
= RMxSessionSendMessage( inMessage
->session
, inMessage
->opcode
, err
, "" );
1132 //===========================================================================================================================
1133 // DNSServiceRemoveRecord_server
1134 //===========================================================================================================================
1136 DEBUG_LOCAL
void DNSServiceRemoveRecord_server( RMxMessage
*inMessage
)
1141 DNSServiceFlags flags
;
1144 DNSRecordRef directObj
;
1147 check( inMessage
->session
);
1148 ref
= (DNSServiceRef
) inMessage
->context
;
1149 require_action( ref
, exit
, err
= kNotInitializedErr
);
1150 require_action( ( ref
->opcode
== kRMxOpCodeRegister
) || ( ref
->opcode
== kRMxOpCodeCreateConnection
), exit
, err
= kTypeErr
);
1151 check( ref
->directObj
);
1153 // Extract parameters from the message.
1155 err
= RMxUnpack( inMessage
->recvData
, inMessage
->recvSize
, "ww", &id
, &flags
);
1156 require_noerr( err
, exit
);
1158 dlog( kDebugLevelTrace
, DEBUG_NAME
"%s: id=%d, flags=0x%08X\n", __ROUTINE__
, id
, flags
);
1160 // Find the record with the specified ID, remove it from the list, and free it.
1162 for( p
= &ref
->records
; *p
; p
= &( *p
)->next
)
1164 if( ( *p
)->id
== id
)
1170 require_action( obj
, exit
, err
= kNotFoundErr
);
1173 directObj
= obj
->directObj
;
1177 err
= DNSServiceRemoveRecord_direct( ref
->directObj
, directObj
, flags
);
1178 require_noerr( err
, exit
);
1183 err
= RMxSessionSendMessage( inMessage
->session
, inMessage
->opcode
, err
, "" );
1190 #pragma mark == DNS-SD Service Discovery ==
1193 //===========================================================================================================================
1194 // DNSServiceBrowse_server
1195 //===========================================================================================================================
1197 DEBUG_LOCAL
void DNSServiceBrowse_server( RMxMessage
*inMessage
)
1201 DNSServiceFlags flags
;
1202 uint32_t interfaceIndex
;
1204 const char * domain
;
1208 check( inMessage
->session
);
1209 require_action( !inMessage
->session
->message
.context
, exit
, err
= kTypeErr
);
1211 // Extract parameters from the message.
1213 err
= RMxUnpack( inMessage
->recvData
, inMessage
->recvSize
, "wwss", &flags
, &interfaceIndex
, &type
, NULL
, &domain
, NULL
);
1214 require_noerr( err
, exit
);
1216 dlog( kDebugLevelTrace
, DEBUG_NAME
"%s: flags=0x%08X, ifi=%d, type=\"%s\", domain=\"%s\"\n",
1217 __ROUTINE__
, flags
, interfaceIndex
, type
, domain
);
1219 // Allocate and initialize the object.
1221 obj
= (DNSServiceRef
) calloc( 1, sizeof( *obj
) );
1222 require_action( obj
, exit
, err
= kNoMemoryErr
);
1224 obj
->opcode
= inMessage
->opcode
;
1225 obj
->session
= inMessage
->session
;
1227 err
= DNSServiceBrowse_direct( &obj
->directObj
, flags
, interfaceIndex
, type
, domain
, DNSServiceBrowseCallBack_server
, obj
);
1228 require_noerr( err
, exit
);
1232 inMessage
->session
->message
.context
= obj
;
1238 err
= RMxSessionSendMessage( inMessage
->session
, inMessage
->opcode
, err
, "" );
1243 DNSServiceRefDeallocate_server( obj
);
1247 //===========================================================================================================================
1248 // DNSServiceBrowseCallBack_server
1249 //===========================================================================================================================
1251 DEBUG_LOCAL
void CALLBACK_COMPAT
1252 DNSServiceBrowseCallBack_server(
1253 DNSServiceRef inRef
,
1254 DNSServiceFlags inFlags
,
1255 uint32_t inInterfaceIndex
,
1256 DNSServiceErrorType inErrorCode
,
1257 const char * inName
,
1258 const char * inType
,
1259 const char * inDomain
,
1265 DEBUG_UNUSED( inRef
);
1270 obj
= (DNSServiceRef
) inContext
;
1272 check( obj
->session
);
1274 err
= RMxSessionSendMessage( obj
->session
, kRMxOpCodeBrowse
, kNoErr
, "wwwsss",
1275 inFlags
, inInterfaceIndex
, inErrorCode
, inName
, inType
, inDomain
);
1283 //===========================================================================================================================
1284 // DNSServiceResolve_server
1285 //===========================================================================================================================
1287 DEBUG_LOCAL
void DNSServiceResolve_server( RMxMessage
*inMessage
)
1291 DNSServiceFlags flags
;
1292 uint32_t interfaceIndex
;
1295 const char * domain
;
1299 check( inMessage
->session
);
1300 require_action( !inMessage
->session
->message
.context
, exit
, err
= kTypeErr
);
1302 // Extract parameters from the message.
1304 err
= RMxUnpack( inMessage
->recvData
, inMessage
->recvSize
, "wwsss",
1305 &flags
, &interfaceIndex
, &name
, NULL
, &type
, NULL
, &domain
, NULL
);
1306 require_noerr( err
, exit
);
1308 dlog( kDebugLevelTrace
, DEBUG_NAME
"%s: flags=0x%08X, ifi=%d, name=\"%s\", type=\"%s\", domain=\"%s\"\n",
1309 __ROUTINE__
, flags
, interfaceIndex
, name
, type
, domain
);
1311 // Allocate and initialize the object.
1313 obj
= (DNSServiceRef
) calloc( 1, sizeof( *obj
) );
1314 require_action( obj
, exit
, err
= kNoMemoryErr
);
1316 obj
->opcode
= inMessage
->opcode
;
1317 obj
->session
= inMessage
->session
;
1319 err
= DNSServiceResolve_direct( &obj
->directObj
, flags
, interfaceIndex
, name
, type
, domain
,
1320 DNSServiceResolveCallBack_server
, obj
);
1321 require_noerr( err
, exit
);
1325 inMessage
->session
->message
.context
= obj
;
1331 err
= RMxSessionSendMessage( inMessage
->session
, inMessage
->opcode
, err
, "" );
1336 DNSServiceRefDeallocate_server( obj
);
1340 //===========================================================================================================================
1341 // DNSServiceResolveCallBack_server
1342 //===========================================================================================================================
1344 DEBUG_LOCAL
void CALLBACK_COMPAT
1345 DNSServiceResolveCallBack_server(
1346 DNSServiceRef inRef
,
1347 DNSServiceFlags inFlags
,
1348 uint32_t inInterfaceIndex
,
1349 DNSServiceErrorType inErrorCode
,
1350 const char * inFullName
,
1351 const char * inHostName
,
1360 DEBUG_UNUSED( inRef
);
1362 check( inFullName
);
1363 check( inHostName
);
1364 obj
= (DNSServiceRef
) inContext
;
1365 dlog( kDebugLevelTrace
, DEBUG_NAME
"%s: ref=%#p, directRef=%#p\n", __ROUTINE__
, obj
, inRef
);
1367 check( obj
->session
);
1369 err
= RMxSessionSendMessage( obj
->session
, kRMxOpCodeResolve
, kNoErr
, "wwwsshn",
1370 inFlags
, inInterfaceIndex
, inErrorCode
, inFullName
, inHostName
, inPort
, inTXTSize
, inTXT
);
1376 #pragma mark == DNS-SD Special Purpose ==
1379 //===========================================================================================================================
1380 // DNSServiceCreateConnection_server
1381 //===========================================================================================================================
1383 DEBUG_LOCAL
void DNSServiceCreateConnection_server( RMxMessage
*inMessage
)
1390 check( inMessage
->session
);
1391 require_action( !inMessage
->session
->message
.context
, exit
, err
= kTypeErr
);
1393 dlog( kDebugLevelTrace
, DEBUG_NAME
"%s\n", __ROUTINE__
);
1395 // Allocate and initialize the object.
1397 obj
= (DNSServiceRef
) calloc( 1, sizeof( *obj
) );
1398 require_action( obj
, exit
, err
= kNoMemoryErr
);
1400 obj
->opcode
= inMessage
->opcode
;
1401 obj
->session
= inMessage
->session
;
1403 err
= DNSServiceCreateConnection_direct( &obj
->directObj
);
1404 require_noerr( err
, exit
);
1408 inMessage
->session
->message
.context
= obj
;
1414 err
= RMxSessionSendMessage( inMessage
->session
, inMessage
->opcode
, err
, "" );
1419 DNSServiceRefDeallocate_server( obj
);
1423 //===========================================================================================================================
1424 // DNSServiceRegisterRecord_server
1425 //===========================================================================================================================
1427 DEBUG_LOCAL
void DNSServiceRegisterRecord_server( RMxMessage
*inMessage
)
1433 DNSServiceFlags flags
;
1434 uint32_t interfaceIndex
;
1445 check( inMessage
->session
);
1446 ref
= (DNSServiceRef
) inMessage
->context
;
1447 require_action( ref
, exit
, err
= kNotInitializedErr
);
1448 require_action( ref
->opcode
== kRMxOpCodeCreateConnection
, exit
, err
= kTypeErr
);
1449 check( ref
->directObj
);
1451 // Extract parameters from the message.
1453 err
= RMxUnpack( inMessage
->recvData
, inMessage
->recvSize
, "wwwshhnw",
1454 &id
, &flags
, &interfaceIndex
, &name
, NULL
, &rrType
, &rrClass
, &rData
, &rDataSize
, &ttl
);
1455 require_noerr( err
, exit
);
1457 dlog( kDebugLevelTrace
, DEBUG_NAME
1458 "%s: id=%d, flags=0x%08X, ifi=%d, name=\"%s\", rrType=%d, rrClass=%d, rDataSize=%d, ttl=%d\n",
1459 __ROUTINE__
, id
, flags
, interfaceIndex
, name
, rrType
, rrClass
, rDataSize
, ttl
);
1461 // Allocate and initialize the object and add it to the list of records.
1463 obj
= (DNSRecordRef
) calloc( 1, sizeof( *obj
) );
1464 require_action( obj
, exit
, err
= kNoMemoryErr
);
1469 obj
->next
= ref
->records
;
1472 err
= DNSServiceRegisterRecord_direct( ref
->directObj
, &obj
->directObj
, flags
, interfaceIndex
, name
, rrType
, rrClass
,
1473 (uint16_t) rDataSize
, rData
, ttl
, DNSServiceRegisterRecordCallBack_server
, obj
);
1474 require_noerr( err
, exit
);
1481 err
= RMxSessionSendMessage( inMessage
->session
, inMessage
->opcode
, err
, "" );
1486 for( p
= &ref
->records
; *p
; p
= &( *p
)->next
)
1498 //===========================================================================================================================
1499 // DNSServiceRegisterRecordCallBack_server
1500 //===========================================================================================================================
1502 DEBUG_LOCAL
void CALLBACK_COMPAT
1503 DNSServiceRegisterRecordCallBack_server(
1504 DNSServiceRef inRef
,
1505 DNSRecordRef inRecordRef
,
1506 DNSServiceFlags inFlags
,
1507 DNSServiceErrorType inErrorCode
,
1510 DNSRecordRef record
;
1514 DEBUG_UNUSED( inRef
);
1515 DEBUG_UNUSED( inRecordRef
);
1517 record
= (DNSRecordRef
) inContext
;
1519 obj
= record
->owner
;
1521 check( obj
->session
);
1523 err
= RMxSessionSendMessage( obj
->session
, kRMxOpCodeRegisterRecord
, kNoErr
, "www", inFlags
, inErrorCode
, record
->id
);
1527 //===========================================================================================================================
1528 // DNSServiceQueryRecord_server
1529 //===========================================================================================================================
1531 DEBUG_LOCAL
void DNSServiceQueryRecord_server( RMxMessage
*inMessage
)
1535 DNSServiceFlags flags
;
1536 uint32_t interfaceIndex
;
1543 check( inMessage
->session
);
1544 require_action( !inMessage
->session
->message
.context
, exit
, err
= kTypeErr
);
1546 // Extract parameters from the message.
1548 err
= RMxUnpack( inMessage
->recvData
, inMessage
->recvSize
, "wwshh",
1549 &flags
, &interfaceIndex
, &name
, NULL
, &rrType
, &rrClass
);
1550 require_noerr( err
, exit
);
1552 dlog( kDebugLevelTrace
, DEBUG_NAME
"%s: flags=0x%08X, ifi=%d, name=\"%s\", rrType=%d, rrClass=%d\n",
1553 __ROUTINE__
, flags
, interfaceIndex
, name
, rrType
, rrClass
);
1555 // Allocate and initialize the object.
1557 obj
= (DNSServiceRef
) calloc( 1, sizeof( *obj
) );
1558 require_action( obj
, exit
, err
= kNoMemoryErr
);
1560 obj
->opcode
= inMessage
->opcode
;
1561 obj
->session
= inMessage
->session
;
1563 err
= DNSServiceQueryRecord_direct( &obj
->directObj
, flags
, interfaceIndex
, name
, rrType
, rrClass
,
1564 DNSServiceQueryRecordCallBack_server
, obj
);
1565 require_noerr( err
, exit
);
1569 inMessage
->session
->message
.context
= obj
;
1575 err
= RMxSessionSendMessage( inMessage
->session
, inMessage
->opcode
, err
, "" );
1580 DNSServiceRefDeallocate_server( obj
);
1584 //===========================================================================================================================
1585 // DNSServiceQueryRecordCallBack_server
1586 //===========================================================================================================================
1588 DEBUG_LOCAL
void CALLBACK_COMPAT
1589 DNSServiceQueryRecordCallBack_server(
1590 DNSServiceRef inRef
,
1591 DNSServiceFlags inFlags
,
1592 uint32_t inInterfaceIndex
,
1593 DNSServiceErrorType inErrorCode
,
1594 const char * inName
,
1597 uint16_t inRDataSize
,
1598 const void * inRData
,
1605 DEBUG_UNUSED( inRef
);
1607 obj
= (DNSServiceRef
) inContext
;
1609 check( obj
->session
);
1611 err
= RMxSessionSendMessage( obj
->session
, kRMxOpCodeQueryRecord
, kNoErr
, "wwwshhnw",
1612 inFlags
, inInterfaceIndex
, inErrorCode
, inName
, inRRType
, inRRClass
, inRDataSize
, inRData
, inTTL
);
1616 //===========================================================================================================================
1617 // DNSServiceReconfirmRecord_server
1618 //===========================================================================================================================
1620 DEBUG_LOCAL
void DNSServiceReconfirmRecord_server( RMxMessage
*inMessage
)
1623 DNSServiceFlags flags
;
1624 uint32_t interfaceIndex
;
1632 check( inMessage
->session
);
1633 require_action( !inMessage
->session
->message
.context
, exit
, err
= kTypeErr
);
1635 // Extract parameters from the message.
1637 err
= RMxUnpack( inMessage
->recvData
, inMessage
->recvSize
, "wwshhn",
1638 &flags
, &interfaceIndex
, &name
, NULL
, &rrType
, &rrClass
, &rData
, &rDataSize
);
1639 require_noerr( err
, exit
);
1641 dlog( kDebugLevelTrace
, "\n" DEBUG_NAME
"%s: flags=0x%08X, ifi=%d, name=\"%s\", rrType=%d, rrClass=%d, rDataSize=%d\n",
1642 __ROUTINE__
, flags
, interfaceIndex
, name
, rrType
, rrClass
, rDataSize
);
1644 // Trigger the reconfirm then cause the session to quit.
1646 DNSServiceReconfirmRecord_direct( flags
, interfaceIndex
, name
, rrType
, rrClass
, (uint16_t) rDataSize
, rData
);
1647 require_noerr( err
, exit
);
1650 inMessage
->session
->quit
= true;