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):
27 $Log: DNSSDDirect.c,v $
28 Revision 1.7 2004/06/05 00:04:27 cheshire
29 <rdar://problem/3668639>: wide-area domains should be returned in reg. domain enumeration
31 Revision 1.6 2004/05/08 12:25:50 bradley
32 Changed to use symbolic enums to prevent some compilers from treating it as a sign conversion.
34 Revision 1.5 2004/05/06 18:42:58 ksekar
35 General dns_sd.h API cleanup, including the following radars:
36 <rdar://problem/3592068>: Remove flags with zero value
37 <rdar://problem/3479569>: Passing in NULL causes a crash.
39 Revision 1.4 2004/04/15 06:55:50 bradley
40 Changed resolving to manually query for SRV and TXT records instead of using mDNS_StartResolveService.
41 This avoids extra A/AAAA record queries and allows local-only resolves to work with normal services.
43 Revision 1.3 2004/04/15 01:00:05 bradley
44 Removed support for automatically querying for A/AAAA records when resolving names. Platforms
45 without .local name resolving support will need to manually query for A/AAAA records as needed.
47 Revision 1.2 2004/04/09 21:03:14 bradley
48 Changed port numbers to use network byte order for consistency with other platforms.
50 Revision 1.1 2004/01/30 02:46:15 bradley
51 Portable implementation of the DNS-SD API. This interacts with mDNSCore to perform all the real work
52 of the DNS-SD API. This code does not rely on any platform-specifics so it should run on any platform
53 with an mDNS platform plugin available. Software that cannot or does not want to use the IPC mechanism
54 (e.g. Windows CE, VxWorks, etc.) can use this code directly without any of the IPC pieces.
60 #include "CommonServices.h"
61 #include "DebugServices.h"
65 #if( DNS_SD_DIRECT_ENABLED )
67 #include "mDNSClientAPI.h"
69 #include "DNSSDDirect.h"
76 #pragma mark == Constants ==
79 //===========================================================================================================================
81 //===========================================================================================================================
83 #define DEBUG_NAME "[DNS-SD Direct] "
85 typedef uint32_t DNSServiceRegisterFlags
;
87 #define kDNSServiceRegisterFlagsAutoName ( 1 << 0 )
88 #define kDNSServiceRegisterFlagsAutoNameOnFree ( 1 << 1 )
89 #define kDNSServiceRegisterFlagsRenameOnConflict ( 1 << 2 )
92 #pragma mark == Structures ==
95 //===========================================================================================================================
97 //===========================================================================================================================
99 typedef void ( *DNSServiceRefReleaseCallBack
)( DNSServiceRef inRef
);
103 typedef struct _DNSServiceRef_t _DNSServiceRef_t
;
104 struct _DNSServiceRef_t
107 DNSServiceRefReleaseCallBack releaseCallBack
;
112 struct // EnumerateDomains
114 DNSQuestion question
;
115 mDNSBool questionActive
;
116 DNSQuestion defaultQuestion
;
117 mDNSBool defaultQuestionActive
;
118 DNSServiceDomainEnumReply callback
;
124 ServiceRecordSet
* set
;
126 DNSServiceRegisterFlags flags
;
127 DNSServiceRegisterReply callback
;
133 DNSQuestion question
;
134 mDNSBool questionActive
;
135 DNSServiceBrowseReply callback
;
141 DNSServiceFlags flags
;
142 DNSQuestion srvQuestion
;
143 mDNSBool srvQuestionActive
;
144 const ResourceRecord
* srvAnswer
;
145 DNSQuestion txtQuestion
;
146 mDNSBool txtQuestionActive
;
147 const ResourceRecord
* txtAnswer
;
148 DNSServiceResolveReply callback
;
152 struct // CreateConnection
154 DNSRecordRef records
;
160 DNSQuestion question
;
161 mDNSBool questionActive
;
162 DNSServiceQueryRecordReply callback
;
171 typedef struct _DNSRecordRef_t _DNSRecordRef_t
;
172 struct _DNSRecordRef_t
176 struct // Service-based records (i.e. DNSServiceRegister-based DNSServiceRef's)
178 ExtraResourceRecord extra
;
182 struct // Connection-based records (i.e. DNSServiceCreateConnection-based DNSServiceRef's)
186 DNSServiceRegisterRecordReply callback
;
194 // WARNING: Do not add fields after the resource record. That is where oversized RData space is allocated.
197 #define kDNSRecordServiceFixedSize sizeof_field( _DNSRecordRef_t, u.service )
198 #define kDNSRecordConnectionFixedSize sizeof_field( _DNSRecordRef_t, u.connection )
201 #pragma mark == Prototypes ==
204 //===========================================================================================================================
206 //===========================================================================================================================
210 #define DNSServiceLock() mDNSPlatformLock( gMDNSPtr )
211 #define DNSServiceUnlock() mDNSPlatformUnlock( gMDNSPtr )
213 DEBUG_LOCAL
void DNSServiceMDNSCallBack( mDNS
* const inMDNS
, mStatus inStatus
);
215 // Domain Enumeration
217 DEBUG_LOCAL
void DNSServiceEnumerateDomainsRelease_direct( DNSServiceRef inRef
);
219 DNSServiceEnumerateDomainsCallBack_direct(
221 DNSQuestion
* inQuestion
,
222 const ResourceRecord
* const inAnswer
,
223 mDNSBool inAddRecord
);
227 DEBUG_LOCAL
void DNSServiceBrowseRelease_direct( DNSServiceRef inRef
);
229 DNSServiceBrowseCallBack_direct(
231 DNSQuestion
* inQuestion
,
232 const ResourceRecord
* const inAnswer
,
233 mDNSBool inAddRecord
);
235 DEBUG_LOCAL
void DNSServiceResolveRelease_direct( DNSServiceRef inRef
);
237 DNSServiceResolveCallBack_direct(
239 DNSQuestion
* inQuestion
,
240 const ResourceRecord
* const inAnswer
,
241 mDNSBool inAddRecord
);
243 // Service Registration
245 DEBUG_LOCAL
void DNSServiceRegisterRelease_direct( DNSServiceRef inRef
);
246 DEBUG_LOCAL
void DNSServiceRegisterCallBack_direct( mDNS
* const inMDNS
, ServiceRecordSet
* const inSet
, mStatus inResult
);
247 DEBUG_LOCAL
void DNSServiceRegisterFree_direct( DNSServiceRef inRef
);
249 DEBUG_LOCAL
void DNSServiceUpdateRecordCallBack_direct( mDNS
* const inMDNS
, AuthRecord
* const inRR
, RData
*inOldRData
);
253 DEBUG_LOCAL
void DNSServiceCreateConnectionRelease_direct( DNSServiceRef inRef
);
254 DEBUG_LOCAL DNSRecordRef
DNSServiceConnectionRecordRemove_direct( DNSServiceRef inRef
, DNSRecordRef inRecordRef
);
256 DEBUG_LOCAL
void DNSServiceRegisterRecordCallBack_direct( mDNS
*const inMDNS
, AuthRecord
*const inRR
, mStatus inResult
);
258 DEBUG_LOCAL
void DNSServiceQueryRecordRelease_direct( DNSServiceRef inRef
);
260 DNSServiceQueryRecordCallBack_direct(
262 DNSQuestion
* inQuestion
,
263 const ResourceRecord
* const inAnswer
,
264 mDNSBool inAddRecord
);
267 #pragma mark == Globals ==
270 //===========================================================================================================================
272 //===========================================================================================================================
275 DEBUG_LOCAL mDNS
* gMDNSPtr
= NULL
;
276 DEBUG_LOCAL CacheRecord
* gMDNSCache
= NULL
;
277 DEBUG_LOCAL DNSServiceRef gDNSServiceRefList
= NULL
;
278 DEBUG_LOCAL DNSServiceRef gDNSCurrentServiceRef
= NULL
;
279 DEBUG_LOCAL DNSRecordRef gDNSCurrentRecord
= NULL
;
283 #pragma mark == General ==
286 //===========================================================================================================================
287 // DNSServiceInitialize_direct
288 //===========================================================================================================================
290 DNSServiceErrorType
DNSServiceInitialize_direct( DNSServiceInitializeFlags inFlags
, int inCacheEntryCount
)
292 DNSServiceErrorType err
;
295 dlog( kDebugLevelTrace
, DEBUG_NAME
"initializing (flags=0x%08X, cache=%d/%d)\n", (int) inFlags
,
296 inCacheEntryCount
, ( inCacheEntryCount
== 0 ) ? kDNSServiceCacheEntryCountDefault
: inCacheEntryCount
);
298 // Allocate the record cache.
300 if( inCacheEntryCount
== 0 )
302 inCacheEntryCount
= kDNSServiceCacheEntryCountDefault
;
304 gMDNSCache
= (CacheRecord
*) malloc( inCacheEntryCount
* sizeof( *gMDNSCache
) );
305 require_action( gMDNSCache
, exit
, err
= kDNSServiceErr_NoMemory
);
309 if( inFlags
& kDNSServiceInitializeFlagsAdvertise
)
311 advertise
= mDNS_Init_AdvertiseLocalAddresses
;
315 advertise
= mDNS_Init_DontAdvertiseLocalAddresses
;
317 err
= mDNS_Init( &gMDNS
, NULL
, gMDNSCache
, (mDNSu32
) inCacheEntryCount
, advertise
, DNSServiceMDNSCallBack
, NULL
);
318 require_noerr( err
, exit
);
319 err
= gMDNS
.mDNSPlatformStatus
;
320 require_noerr( err
, exit
);
325 dlog( kDebugLevelTrace
, DEBUG_NAME
"initializing done (err=%d %m)\n", err
, err
);
328 DNSServiceFinalize_direct();
333 //===========================================================================================================================
334 // DNSServiceFinalize_direct
335 //===========================================================================================================================
337 void DNSServiceFinalize_direct( void )
339 dlog( kDebugLevelTrace
, DEBUG_NAME
"finalizing\n" );
343 mDNS_Close( &gMDNS
);
349 gMDNSCache
= mDNSNULL
;
352 dlog( kDebugLevelTrace
, DEBUG_NAME
"finalizing done\n" );
355 //===========================================================================================================================
356 // DNSServiceMDNSCallBack
357 //===========================================================================================================================
359 DEBUG_LOCAL
void DNSServiceMDNSCallBack( mDNS
* const inMDNS
, mStatus inStatus
)
361 DEBUG_USE_ONLY( inMDNS
);
364 dlog( kDebugLevelTrace
, DEBUG_NAME
"MDNS callback (status=%d)\n", inStatus
);
366 if( inStatus
== mStatus_ConfigChanged
)
368 // Notify all callbacks that the configuration has changed so they can do any additional processing.
370 // Warning: This is likely to call a user callback, which may change the object lists. Any code walking
371 // Warning: or changing these lists must use the "current" ptr mechanism to protect against this.
374 dlog( kDebugLevelTrace
, DEBUG_NAME
"handling ConfigChanged\n" );
376 check_string( !gDNSCurrentServiceRef
, "somebody is already using gDNSCurrentServiceRef!" );
377 gDNSCurrentServiceRef
= gDNSServiceRefList
;
378 while( gDNSCurrentServiceRef
)
382 obj
= gDNSCurrentServiceRef
;
383 gDNSCurrentServiceRef
= obj
->next
;
385 // Call the callback with the ConfigChanged error code. Use the releaseCallBack to determine the type.
387 if( obj
->releaseCallBack
== DNSServiceEnumerateDomainsRelease_direct
)
389 obj
->u
.domain
.callback( obj
, 0, 0, kDNSServiceErr_ConfigChanged
, "", obj
->context
);
391 else if( obj
->releaseCallBack
== DNSServiceRegisterRelease_direct
)
393 // If auto-renaming and the system name has changed then trigger a re-register with the new name.
395 if( obj
->u
.reg
.flags
& kDNSServiceRegisterFlagsAutoName
)
397 if( !SameDomainLabel( obj
->u
.reg
.name
.c
, gMDNSPtr
->nicelabel
.c
) )
401 obj
->u
.reg
.flags
|= kDNSServiceRegisterFlagsAutoNameOnFree
;
402 err
= mDNS_DeregisterService( gMDNSPtr
, obj
->u
.reg
.set
);
408 check_string( obj
->u
.reg
.callback
, "not auto-naming, but no callback?" );
410 obj
->u
.reg
.callback( obj
, 0, kDNSServiceErr_ConfigChanged
, "", "", "", obj
->context
);
413 else if( obj
->releaseCallBack
== DNSServiceBrowseRelease_direct
)
415 obj
->u
.browse
.callback( obj
, 0, 0, kDNSServiceErr_ConfigChanged
, "", "", "", obj
->context
);
417 else if( obj
->releaseCallBack
== DNSServiceResolveRelease_direct
)
419 obj
->u
.resolve
.callback( obj
, 0, 0, kDNSServiceErr_ConfigChanged
, "", "", 0, 0, NULL
, obj
->context
);
421 else if( obj
->releaseCallBack
== DNSServiceCreateConnectionRelease_direct
)
423 check_string( !gDNSCurrentRecord
, "somebody is already using gDNSCurrentRecord!" );
424 gDNSCurrentRecord
= obj
->u
.connection
.records
;
425 while( gDNSCurrentRecord
)
429 record
= gDNSCurrentRecord
;
430 gDNSCurrentRecord
= record
->u
.connection
.next
;
432 record
->u
.connection
.callback( record
->u
.connection
.owner
, record
, 0, kDNSServiceErr_ConfigChanged
,
433 record
->u
.connection
.context
);
436 else if( obj
->releaseCallBack
== DNSServiceQueryRecordRelease_direct
)
438 obj
->u
.query
.callback( obj
, 0, 0, kDNSServiceErr_ConfigChanged
, "", 0, 0, 0,NULL
, 0, obj
->context
);
449 //===========================================================================================================================
450 // DNSServiceRefDeallocate_direct
451 //===========================================================================================================================
453 void DNSServiceRefDeallocate_direct( DNSServiceRef inRef
)
457 dlog( kDebugLevelNotice
, DEBUG_NAME
"%s: %#p\n", __ROUTINE__
, inRef
);
464 // Remove the object from the list.
466 for( p
= &gDNSServiceRefList
; *p
; p
= &( *p
)->next
)
475 // Release the object if it was found.
481 // If somebody will be looking at this object next, move the current ptr to the next object.
483 if( inRef
== gDNSCurrentServiceRef
)
485 dlog( kDebugLevelInfo
, DEBUG_NAME
"deleting gDNSCurrentServiceRef (%#p)\n", inRef
);
486 gDNSCurrentServiceRef
= inRef
->next
;
489 check( inRef
->releaseCallBack
);
490 if( inRef
->releaseCallBack
)
492 inRef
->releaseCallBack( inRef
);
501 #pragma mark == Domain Enumeration ==
504 //===========================================================================================================================
505 // DNSServiceEnumerateDomains_direct
506 //===========================================================================================================================
509 DNSServiceEnumerateDomains_direct(
510 DNSServiceRef
* outRef
,
511 const DNSServiceFlags inFlags
,
512 const uint32_t inInterfaceIndex
,
513 const DNSServiceDomainEnumReply inCallBack
,
516 DNSServiceErrorType err
;
518 mDNS_DomainType type
;
519 mDNS_DomainType defaultType
;
520 DNSServiceFlags flags
;
521 mDNSInterfaceID interfaceID
;
525 require_action( outRef
, exit
, err
= kDNSServiceErr_BadParam
);
526 require_action( ( inFlags
== kDNSServiceFlagsBrowseDomains
) ||
527 ( inFlags
== kDNSServiceFlagsRegistrationDomains
),
528 exit
, err
= kDNSServiceErr_BadFlags
);
529 require_action( inCallBack
, exit
, err
= kDNSServiceErr_BadParam
);
531 // Allocate and initialize the object.
533 obj
= (DNSServiceRef
) calloc( 1, sizeof( *obj
) );
534 require_action( obj
, exit
, err
= kDNSServiceErr_NoMemory
);
536 obj
->releaseCallBack
= DNSServiceEnumerateDomainsRelease_direct
;
537 obj
->context
= inContext
;
538 obj
->u
.domain
.callback
= inCallBack
;
540 obj
->next
= gDNSServiceRefList
;
541 gDNSServiceRefList
= obj
;
543 // Start the browse operations.
545 if( inFlags
& kDNSServiceFlagsRegistrationDomains
)
547 type
= mDNS_DomainTypeRegistration
;
548 defaultType
= mDNS_DomainTypeRegistrationDefault
;
552 type
= mDNS_DomainTypeBrowse
;
553 defaultType
= mDNS_DomainTypeBrowseDefault
;
555 interfaceID
= mDNSPlatformInterfaceIDfromInterfaceIndex( gMDNSPtr
, inInterfaceIndex
);
557 err
= mDNS_GetDomains( gMDNSPtr
, &obj
->u
.domain
.question
, type
, NULL
, interfaceID
,
558 DNSServiceEnumerateDomainsCallBack_direct
, obj
);
559 require_noerr( err
, exit
);
560 obj
->u
.domain
.questionActive
= mDNStrue
;
562 err
= mDNS_GetDomains( gMDNSPtr
, &obj
->u
.domain
.defaultQuestion
, defaultType
, NULL
, interfaceID
,
563 DNSServiceEnumerateDomainsCallBack_direct
, obj
);
564 require_noerr( err
, exit
);
565 obj
->u
.domain
.defaultQuestionActive
= mDNStrue
;
567 // Call back immediately with "local." since that is always available for all types of browsing.
569 flags
= kDNSServiceFlagsDefault
| kDNSServiceFlagsAdd
;
570 inCallBack( obj
, flags
, inInterfaceIndex
, kDNSServiceErr_NoError
, "local.", inContext
);
580 DNSServiceRefDeallocate_direct( obj
);
586 //===========================================================================================================================
587 // DNSServiceEnumerateDomainsRelease_direct
589 // Warning: Assumes the mDNS platform lock is held.
590 //===========================================================================================================================
592 DEBUG_LOCAL
void DNSServiceEnumerateDomainsRelease_direct( DNSServiceRef inRef
)
598 if( inRef
->u
.domain
.questionActive
)
600 err
= mDNS_StopGetDomains( gMDNSPtr
, &inRef
->u
.domain
.question
);
603 if( inRef
->u
.domain
.defaultQuestionActive
)
605 err
= mDNS_StopGetDomains( gMDNSPtr
, &inRef
->u
.domain
.defaultQuestion
);
611 //===========================================================================================================================
612 // DNSServiceEnumerateDomainsCallBack_direct
614 // Warning: Assumes the mDNS platform lock is held (held by mDNS before invoking this callback).
615 //===========================================================================================================================
618 DNSServiceEnumerateDomainsCallBack_direct(
620 DNSQuestion
* inQuestion
,
621 const ResourceRecord
* const inAnswer
,
622 mDNSBool inAddRecord
)
625 DNSServiceFlags flags
;
626 uint32_t interfaceIndex
;
627 char domain
[ MAX_ESCAPED_DOMAIN_NAME
];
629 DEBUG_UNUSED( inMDNS
);
632 obj
= (DNSServiceRef
) inQuestion
->QuestionContext
;
635 flags
= inAddRecord
? kDNSServiceFlagsAdd
: kDNSServiceFlagsNone
;
638 if( inQuestion
== &obj
->u
.domain
.defaultQuestion
)
640 flags
|= kDNSServiceFlagsDefault
;
643 interfaceIndex
= mDNSPlatformInterfaceIndexfromInterfaceID( &gMDNS
, inAnswer
->InterfaceID
);
644 ConvertDomainNameToCString( &inAnswer
->rdata
->u
.name
, domain
);
646 obj
->u
.domain
.callback( obj
, flags
, interfaceIndex
, kDNSServiceErr_NoError
, domain
, obj
->context
);
651 #pragma mark == Service Registration ==
654 //===========================================================================================================================
655 // DNSServiceRegister_direct
656 //===========================================================================================================================
659 DNSServiceRegister_direct(
660 DNSServiceRef
* outRef
,
661 DNSServiceFlags inFlags
,
662 uint32_t inInterfaceIndex
,
665 const char * inDomain
,
670 DNSServiceRegisterReply inCallBack
,
673 DNSServiceErrorType err
;
684 mDNSInterfaceID interfaceID
;
688 require_action( outRef
, exit
, err
= kDNSServiceErr_BadReference
);
689 require_action( ( inFlags
== 0 ) || ( inFlags
== kDNSServiceFlagsNoAutoRename
), exit
, err
= kDNSServiceErr_BadFlags
);
690 autoName
= !inName
|| ( *inName
== '\0' );
691 require_action( !autoName
|| !( inFlags
& kDNSServiceFlagsNoAutoRename
), exit
, err
= kDNSServiceErr_BadParam
);
692 require_action( inType
, exit
, err
= kDNSServiceErr_BadParam
);
693 require_action( inTXT
|| ( inTXTSize
== 0 ), exit
, err
= kDNSServiceErr_BadParam
);
694 require_action( inCallBack
|| autoName
, exit
, err
= kDNSServiceErr_BadParam
);
696 // Convert all the input strings and make sure they are valid. Use the system name if auto-naming.
700 name
= gMDNSPtr
->nicelabel
;
704 ok
= MakeDomainLabelFromLiteralString( &name
, inName
);
705 require_action( ok
, exit
, err
= kDNSServiceErr_BadParam
);
708 ok
= MakeDomainNameFromDNSNameString( &type
, inType
) != NULL
;
709 require_action( ok
, exit
, err
= kDNSServiceErr_BadParam
);
711 if( !inDomain
|| ( *inDomain
== '\0' ) )
715 ok
= MakeDomainNameFromDNSNameString( &domain
, inDomain
) != NULL
;
716 require_action( ok
, exit
, err
= kDNSServiceErr_BadParam
);
718 // Set up the host name (if not using the default).
721 if( inHost
&& ( *inHost
!= '\0' ) )
724 ok
= MakeDomainNameFromDNSNameString( host
, inHost
) != NULL
;
725 require_action( ok
, exit
, err
= kDNSServiceErr_BadParam
);
727 AppendDomainName( host
, &domain
);
730 // Allocate and initialize the object.
732 obj
= (DNSServiceRef
) calloc( 1, sizeof( *obj
) );
733 require_action( obj
, exit
, err
= kDNSServiceErr_NoMemory
);
735 obj
->releaseCallBack
= DNSServiceRegisterRelease_direct
;
736 obj
->context
= inContext
;
737 obj
->u
.reg
.flags
= 0;
740 obj
->u
.reg
.flags
|= kDNSServiceRegisterFlagsAutoName
;
742 if( !( inFlags
& kDNSServiceFlagsNoAutoRename
) )
744 obj
->u
.reg
.flags
|= kDNSServiceRegisterFlagsRenameOnConflict
;
746 obj
->u
.reg
.callback
= inCallBack
;
748 // Allocate space for the records, including any extra space to handle an oversized TXT record.
750 size
= sizeof( ServiceRecordSet
);
751 if( inTXTSize
> sizeof( RDataBody
) )
753 size
+= ( inTXTSize
- sizeof( RDataBody
) );
755 obj
->u
.reg
.set
= (ServiceRecordSet
*) calloc( 1, size
);
756 require_action( obj
->u
.reg
.set
, exit
, err
= kDNSServiceErr_NoMemory
);
758 obj
->next
= gDNSServiceRefList
;
759 gDNSServiceRefList
= obj
;
761 // Register the service with mDNS.
763 port
.NotAnInteger
= inPort
;
764 interfaceID
= mDNSPlatformInterfaceIDfromInterfaceIndex( gMDNSPtr
, inInterfaceIndex
);
766 err
= mDNS_RegisterService( gMDNSPtr
, obj
->u
.reg
.set
, &name
, &type
, &domain
, host
, port
,
767 (const mDNSu8
*) inTXT
, inTXTSize
, NULL
, 0, interfaceID
, DNSServiceRegisterCallBack_direct
, obj
);
768 require_noerr( err
, exit
);
778 DNSServiceRegisterFree_direct( obj
);
784 //===========================================================================================================================
785 // DNSServiceRegisterRelease_direct
787 // Warning: Assumes the mDNS platform lock is held.
788 //===========================================================================================================================
790 DEBUG_LOCAL
void DNSServiceRegisterRelease_direct( DNSServiceRef inRef
)
796 // Deregister the service. If an error occurs (which should never happen), we have to assume that mDNS does not
797 // know about the registration and will not call us back with mStatus_MemFree so we free the memory here.
798 // Otherwise, mDNS will call us back with a mStatus_MemFree error code when it is safe for us to free the memory.
800 err
= mDNS_DeregisterService( gMDNSPtr
, inRef
->u
.reg
.set
);
802 if( err
!= mStatus_NoError
)
804 DNSServiceRegisterFree_direct( inRef
);
808 //===========================================================================================================================
809 // DNSServiceRegisterCallBack_direct
811 // Warning: Assumes the mDNS platform lock is held (held by mDNS before invoking this callback).
812 //===========================================================================================================================
814 DEBUG_LOCAL
void DNSServiceRegisterCallBack_direct( mDNS
* const inMDNS
, ServiceRecordSet
* const inSet
, mStatus inResult
)
821 char nameString
[ MAX_DOMAIN_LABEL
+ 1 ];
822 char typeString
[ MAX_ESCAPED_DOMAIN_NAME
];
823 char domainString
[ MAX_ESCAPED_DOMAIN_NAME
];
825 DEBUG_UNUSED( inMDNS
);
826 DEBUG_UNUSED( inSet
);
828 obj
= (DNSServiceRef
) inSet
->ServiceContext
;
831 if( inResult
== mStatus_NoError
)
833 // Successful Registration.
835 if( obj
->u
.reg
.callback
)
837 ok
= DeconstructServiceName( &inSet
->RR_SRV
.resrec
.name
, &name
, &type
, &domain
);
840 ConvertDomainLabelToCString_unescaped( &name
, nameString
);
841 ConvertDomainNameToCString( &type
, typeString
);
842 ConvertDomainNameToCString( &domain
, domainString
);
844 obj
->u
.reg
.callback( obj
, 0, kDNSServiceErr_NoError
, nameString
, typeString
, domainString
, obj
->context
);
847 else if( inResult
== mStatus_MemFree
)
849 // If the AutoNameOnFree flag is set, it means we should re-register with the system name instead of freeing.
850 // Otherwise, mDNS is done with the memory so we can safely free it.
852 if( obj
->u
.reg
.flags
& kDNSServiceRegisterFlagsAutoNameOnFree
)
854 obj
->u
.reg
.flags
&= ~kDNSServiceRegisterFlagsAutoNameOnFree
;
855 obj
->u
.reg
.name
= gMDNSPtr
->nicelabel
;
856 inResult
= mDNS_RenameAndReregisterService( gMDNSPtr
, obj
->u
.reg
.set
, &obj
->u
.reg
.name
);
857 check_noerr( inResult
);
859 if( inResult
!= mStatus_NoError
)
861 DNSServiceRegisterFree_direct( obj
);
864 else if( inResult
== mStatus_NameConflict
)
866 // Name conflict. If the auto renaming flags are enabled silently rename and re-register.
867 // Otherwise, mDNS will not send call us again with mStatus_MemFree so free the memory here.
869 if( obj
->u
.reg
.flags
& ( kDNSServiceRegisterFlagsAutoName
| kDNSServiceRegisterFlagsRenameOnConflict
) )
871 inResult
= mDNS_RenameAndReregisterService( gMDNSPtr
, obj
->u
.reg
.set
, mDNSNULL
);
873 if( inResult
!= mStatus_NoError
)
875 if( obj
->u
.reg
.callback
)
877 obj
->u
.reg
.callback( obj
, 0, kDNSServiceErr_NameConflict
, "", "", "", obj
->context
);
879 DNSServiceRegisterFree_direct( obj
);
884 dlog( kDebugLevelNotice
, "unknown register result (%d)\n", inResult
);
885 if( obj
->u
.reg
.callback
)
887 obj
->u
.reg
.callback( obj
, 0, inResult
, "", "", "", obj
->context
);
892 //===========================================================================================================================
893 // DNSServiceRegisterFree_direct
894 //===========================================================================================================================
896 DEBUG_LOCAL
void DNSServiceRegisterFree_direct( DNSServiceRef inRef
)
900 if( inRef
->u
.reg
.set
)
902 // Note: Each "Extras" record is a "DNSServiceRef", which is just a syntactic wrapper for ExtraResourceRecord.
903 // This avoids the need for casting and simplifies access, but still allows the following loop to work correctly.
905 while( inRef
->u
.reg
.set
->Extras
)
907 ExtraResourceRecord
* extra
;
909 extra
= inRef
->u
.reg
.set
->Extras
;
910 inRef
->u
.reg
.set
->Extras
= extra
->next
;
914 free( inRef
->u
.reg
.set
);
919 //===========================================================================================================================
920 // DNSServiceAddRecord_direct
921 //===========================================================================================================================
924 DNSServiceAddRecord_direct(
926 DNSRecordRef
* outRecordRef
,
927 DNSServiceFlags inFlags
,
929 uint16_t inRDataSize
,
930 const void * inRData
,
933 DNSServiceErrorType err
;
936 ExtraResourceRecord
* extra
;
940 require_action( inRef
, exit
, err
= kDNSServiceErr_BadReference
);
941 require_action( inRef
->releaseCallBack
== DNSServiceRegisterRelease_direct
, exit
, err
= kDNSServiceErr_BadParam
);
942 require_action( inRef
->u
.reg
.set
, exit
, err
= kDNSServiceErr_NotInitialized
);
943 require_action( outRecordRef
, exit
, err
= kDNSServiceErr_BadParam
);
944 require_action( inFlags
== 0, exit
, err
= kDNSServiceErr_BadFlags
);
945 require_action( inRData
&& ( inRDataSize
> 0 ), exit
, err
= kDNSServiceErr_BadParam
);
947 // Allocate and initialize the record. Allocate oversized record space at the end of the record.
949 size
= ( inRDataSize
> sizeof( RDataBody
) ) ? inRDataSize
: sizeof( RDataBody
);
950 obj
= (DNSRecordRef
) calloc( 1, ( kDNSRecordServiceFixedSize
- sizeof( RDataBody
) ) + size
);
951 require_action( obj
, exit
, err
= kDNSServiceErr_NoMemory
);
953 extra
= &obj
->u
.service
.extra
;
954 extra
->r
.resrec
.rrtype
= inRRType
;
955 extra
->r
.resrec
.rdlength
= inRDataSize
;
956 extra
->r
.rdatastorage
.MaxRDLength
= (mDNSu16
) size
;
957 memcpy( extra
->r
.rdatastorage
.u
.data
, inRData
, inRDataSize
);
959 // Register the record with mDNS.
961 err
= mDNS_AddRecordToService( gMDNSPtr
, inRef
->u
.reg
.set
, extra
, &extra
->r
.rdatastorage
, inTTL
);
962 require_noerr( err
, exit
);
966 *outRecordRef
= (DNSRecordRef
) obj
;
978 //===========================================================================================================================
979 // DNSServiceUpdateRecord_direct
980 //===========================================================================================================================
983 DNSServiceUpdateRecord_direct(
985 DNSRecordRef inRecordRef
,
986 DNSServiceFlags inFlags
,
987 uint16_t inRDataSize
,
988 const void * inRData
,
991 DNSServiceErrorType err
;
998 require_action( inRef
, exit
, err
= kDNSServiceErr_BadReference
);
999 require_action( ( inRef
->releaseCallBack
== DNSServiceRegisterRelease_direct
) ||
1000 ( inRef
->releaseCallBack
== DNSServiceCreateConnectionRelease_direct
),
1001 exit
, err
= kDNSServiceErr_BadParam
);
1002 require_action( inRef
->u
.reg
.set
, exit
, err
= kDNSServiceErr_NotInitialized
);
1003 require_action( inFlags
== 0, exit
, err
= kDNSServiceErr_BadFlags
);
1004 require_action( inRData
, exit
, err
= kDNSServiceErr_BadParam
);
1006 // Get the embedded AuthRecord from the DNSRecordRef. Determine the type of DNSServiceRef from the releaseCallBack.
1008 if( inRef
->releaseCallBack
== DNSServiceRegisterRelease_direct
)
1010 rr
= inRecordRef
? &inRecordRef
->u
.service
.extra
.r
: &inRef
->u
.reg
.set
->RR_TXT
;
1012 else if( inRef
->releaseCallBack
== DNSServiceCreateConnectionRelease_direct
)
1014 require_action( inRecordRef
, exit
, err
= kDNSServiceErr_BadReference
);
1015 rr
= &inRecordRef
->u
.connection
.rr
;
1019 dlog( kDebugLevelError
, DEBUG_NAME
"trying to remove a DNSRecordRef with an unsupported DNSServiceRef\n" );
1020 err
= kDNSServiceErr_Unsupported
;
1024 // Allocate and initialize the data. Allocate oversized data at the end of the record.
1026 size
= ( inRDataSize
> sizeof( RDataBody
) ) ? inRDataSize
: sizeof( RDataBody
);
1027 rd
= (RData
*) calloc( 1, ( sizeof( *rd
) - sizeof( RDataBody
) ) + size
);
1028 require_action( rd
, exit
, err
= kDNSServiceErr_NoMemory
);
1030 rd
->MaxRDLength
= (mDNSu16
) size
;
1031 memcpy( rd
->u
.data
, inRData
, inRDataSize
);
1033 // Update the record. A NULL record means to update the primary TXT record.
1035 err
= mDNS_Update( gMDNSPtr
, rr
, inTTL
, inRDataSize
, rd
, DNSServiceUpdateRecordCallBack_direct
);
1036 require_noerr( err
, exit
);
1051 //===========================================================================================================================
1052 // DNSServiceUpdateRecord_direct
1054 // Warning: It is not safe to make any mDNS calls here.
1055 //===========================================================================================================================
1057 DEBUG_LOCAL
void DNSServiceUpdateRecordCallBack_direct( mDNS
* const inMDNS
, AuthRecord
* const inRR
, RData
*inOldRData
)
1059 DEBUG_UNUSED( inMDNS
);
1061 check( inOldRData
);
1063 if( inOldRData
!= &inRR
->rdatastorage
)
1069 //===========================================================================================================================
1070 // DNSServiceRemoveRecord_direct
1071 //===========================================================================================================================
1073 DNSServiceErrorType
DNSServiceRemoveRecord_direct( DNSServiceRef inRef
, DNSRecordRef inRecordRef
, DNSServiceFlags inFlags
)
1075 DNSServiceErrorType err
;
1078 require_action( inRef
, exit
, err
= kDNSServiceErr_BadReference
);
1079 require_action( ( inRef
->releaseCallBack
== DNSServiceRegisterRelease_direct
) ||
1080 ( inRef
->releaseCallBack
== DNSServiceCreateConnectionRelease_direct
),
1081 exit
, err
= kDNSServiceErr_BadParam
);
1082 require_action( inRef
->u
.reg
.set
, exit
, err
= kDNSServiceErr_NotInitialized
);
1083 require_action( inRecordRef
, exit
, err
= kDNSServiceErr_BadParam
);
1084 require_action( inFlags
== 0, exit
, err
= kDNSServiceErr_BadFlags
);
1086 // Get the embedded AuthRecord from the DNSRecordRef. Determine the type of DNSServiceRef from the releaseCallBack.
1088 if( inRef
->releaseCallBack
== DNSServiceRegisterRelease_direct
)
1090 err
= mDNS_RemoveRecordFromService( gMDNSPtr
, inRef
->u
.reg
.set
, &inRecordRef
->u
.service
.extra
);
1091 free( inRecordRef
);
1092 require_noerr( err
, exit
);
1094 else if( inRef
->releaseCallBack
== DNSServiceCreateConnectionRelease_direct
)
1098 inRecordRef
= DNSServiceConnectionRecordRemove_direct( inRef
, inRecordRef
);
1099 require_action( inRecordRef
, exit
, err
= kDNSServiceErr_BadParam
);
1101 freeRR
= ( inRecordRef
->u
.connection
.rr
.resrec
.RecordType
!= kDNSRecordTypeShared
);
1102 err
= mDNS_Deregister( gMDNSPtr
, &inRecordRef
->u
.connection
.rr
);
1104 if( freeRR
|| ( err
!= mStatus_NoError
) )
1106 free( inRecordRef
);
1111 dlog( kDebugLevelError
, DEBUG_NAME
"trying to remove a DNSRecordRef with an unsupported DNSServiceRef\n" );
1112 err
= kDNSServiceErr_Unsupported
;
1123 #pragma mark == Service Discovery ==
1126 //===========================================================================================================================
1127 // DNSServiceBrowse_direct
1128 //===========================================================================================================================
1131 DNSServiceBrowse_direct(
1132 DNSServiceRef
* outRef
,
1133 DNSServiceFlags inFlags
,
1134 uint32_t inInterfaceIndex
,
1135 const char * inType
,
1136 const char * inDomain
,
1137 DNSServiceBrowseReply inCallBack
,
1140 DNSServiceErrorType err
;
1145 mDNSInterfaceID interfaceID
;
1149 require_action( outRef
, exit
, err
= kDNSServiceErr_BadReference
);
1150 require_action( inFlags
== 0, exit
, err
= kDNSServiceErr_BadFlags
);
1151 require_action( inType
, exit
, err
= kDNSServiceErr_BadParam
);
1152 require_action( inCallBack
, exit
, err
= kDNSServiceErr_BadParam
);
1154 // Convert the input strings and make sure they are valid.
1156 ok
= MakeDomainNameFromDNSNameString( &type
, inType
) != NULL
;
1157 require_action( ok
, exit
, err
= kDNSServiceErr_BadParam
);
1159 if( !inDomain
|| ( *inDomain
== '\0' ) )
1161 inDomain
= "local.";
1163 ok
= MakeDomainNameFromDNSNameString( &domain
, inDomain
) != NULL
;
1164 require_action( ok
, exit
, err
= kDNSServiceErr_BadParam
);
1166 // Allocate and initialize the object.
1168 obj
= (DNSServiceRef
) calloc( 1, sizeof( *obj
) );
1169 require_action( obj
, exit
, err
= kDNSServiceErr_NoMemory
);
1171 obj
->releaseCallBack
= DNSServiceBrowseRelease_direct
;
1172 obj
->context
= inContext
;
1173 obj
->u
.browse
.callback
= inCallBack
;
1175 obj
->next
= gDNSServiceRefList
;
1176 gDNSServiceRefList
= obj
;
1180 interfaceID
= mDNSPlatformInterfaceIDfromInterfaceIndex( gMDNSPtr
, inInterfaceIndex
);
1182 err
= mDNS_StartBrowse( gMDNSPtr
, &obj
->u
.browse
.question
, &type
, &domain
, interfaceID
,
1183 DNSServiceBrowseCallBack_direct
, obj
);
1184 require_noerr( err
, exit
);
1185 obj
->u
.browse
.questionActive
= mDNStrue
;
1195 DNSServiceRefDeallocate_direct( obj
);
1201 //===========================================================================================================================
1202 // DNSServiceBrowseRelease_direct
1204 // Warning: Assumes the mDNS platform lock is held.
1205 //===========================================================================================================================
1207 DEBUG_LOCAL
void DNSServiceBrowseRelease_direct( DNSServiceRef inRef
)
1213 if( inRef
->u
.browse
.questionActive
)
1215 err
= mDNS_StopBrowse( gMDNSPtr
, &inRef
->u
.browse
.question
);
1221 //===========================================================================================================================
1222 // DNSServiceBrowseCallBack_direct
1224 // Warning: Assumes the mDNS platform lock is held (held by mDNS before invoking this callback).
1225 //===========================================================================================================================
1228 DNSServiceBrowseCallBack_direct(
1229 mDNS
* const inMDNS
,
1230 DNSQuestion
* inQuestion
,
1231 const ResourceRecord
* const inAnswer
,
1232 mDNSBool inAddRecord
)
1235 DNSServiceFlags flags
;
1236 uint32_t interfaceIndex
;
1241 char nameString
[ MAX_DOMAIN_LABEL
+ 1 ];
1242 char typeString
[ MAX_ESCAPED_DOMAIN_NAME
];
1243 char domainString
[ MAX_ESCAPED_DOMAIN_NAME
];
1245 DEBUG_UNUSED( inMDNS
);
1246 check( inQuestion
);
1247 obj
= (DNSServiceRef
) inQuestion
->QuestionContext
;
1250 flags
= inAddRecord
? kDNSServiceFlagsAdd
: kDNSServiceFlagsNone
;
1251 interfaceIndex
= mDNSPlatformInterfaceIndexfromInterfaceID( &gMDNS
, inAnswer
->InterfaceID
);
1253 ok
= DeconstructServiceName( &inAnswer
->rdata
->u
.name
, &name
, &type
, &domain
);
1256 ConvertDomainLabelToCString_unescaped( &name
, nameString
);
1257 ConvertDomainNameToCString( &type
, typeString
);
1258 ConvertDomainNameToCString( &domain
, domainString
);
1260 obj
->u
.browse
.callback( obj
, flags
, interfaceIndex
, kDNSServiceErr_NoError
, nameString
, typeString
, domainString
,
1268 //===========================================================================================================================
1269 // DNSServiceResolve_direct
1270 //===========================================================================================================================
1273 DNSServiceResolve_direct(
1274 DNSServiceRef
* outRef
,
1275 DNSServiceFlags inFlags
,
1276 uint32_t inInterfaceIndex
,
1277 const char * inName
,
1278 const char * inType
,
1279 const char * inDomain
,
1280 DNSServiceResolveReply inCallBack
,
1283 DNSServiceErrorType err
;
1290 mDNSInterfaceID interfaceID
;
1295 dlog( kDebugLevelTrace
, DEBUG_NAME
"%s\n", __ROUTINE__
);
1296 require_action( outRef
, exit
, err
= kDNSServiceErr_BadReference
);
1297 require_action( inFlags
== 0, exit
, err
= kDNSServiceErr_BadFlags
);
1298 require_action( inName
, exit
, err
= kDNSServiceErr_BadParam
);
1299 require_action( inType
, exit
, err
= kDNSServiceErr_BadParam
);
1300 if( !inDomain
|| ( *inDomain
== '\0' ) ) inDomain
= "local.";
1301 require_action( inCallBack
, exit
, err
= kDNSServiceErr_BadParam
);
1303 // Convert all the input strings and make sure they are valid.
1305 ok
= MakeDomainLabelFromLiteralString( &name
, inName
);
1306 require_action( ok
, exit
, err
= kDNSServiceErr_BadParam
);
1308 ok
= MakeDomainNameFromDNSNameString( &type
, inType
) != NULL
;
1309 require_action( ok
, exit
, err
= kDNSServiceErr_BadParam
);
1311 ok
= MakeDomainNameFromDNSNameString( &domain
, inDomain
) != NULL
;
1312 require_action( ok
, exit
, err
= kDNSServiceErr_BadParam
);
1314 ok
= ConstructServiceName( &fqdn
, &name
, &type
, &domain
) != NULL
;
1315 require_action( ok
, exit
, err
= kDNSServiceErr_BadParam
);
1317 interfaceID
= mDNSPlatformInterfaceIDfromInterfaceIndex( gMDNSPtr
, inInterfaceIndex
);
1319 // Allocate and initialize the object.
1321 obj
= (DNSServiceRef
) calloc( 1, sizeof( *obj
) );
1322 require_action( obj
, exit
, err
= kDNSServiceErr_NoMemory
);
1324 obj
->releaseCallBack
= DNSServiceResolveRelease_direct
;
1325 obj
->context
= inContext
;
1326 obj
->u
.resolve
.flags
= inFlags
;
1327 obj
->u
.resolve
.callback
= inCallBack
;
1329 obj
->next
= gDNSServiceRefList
;
1330 gDNSServiceRefList
= obj
;
1332 // Start the SRV query.
1334 q
= &obj
->u
.resolve
.srvQuestion
;
1335 q
->InterfaceID
= interfaceID
;
1336 AssignDomainName( q
->qname
, fqdn
);
1337 q
->qtype
= kDNSType_SRV
;
1338 q
->qclass
= kDNSClass_IN
;
1339 q
->QuestionCallback
= DNSServiceResolveCallBack_direct
;
1340 q
->QuestionContext
= obj
;
1342 err
= mDNS_StartQuery( gMDNSPtr
, q
);
1343 require_noerr( err
, exit
);
1344 obj
->u
.resolve
.srvQuestionActive
= mDNStrue
;
1346 // Start the TXT query.
1348 q
= &obj
->u
.resolve
.txtQuestion
;
1349 q
->InterfaceID
= interfaceID
;
1350 AssignDomainName( q
->qname
, fqdn
);
1351 q
->qtype
= kDNSType_TXT
;
1352 q
->qclass
= kDNSClass_IN
;
1353 q
->QuestionCallback
= DNSServiceResolveCallBack_direct
;
1354 q
->QuestionContext
= obj
;
1356 err
= mDNS_StartQuery( gMDNSPtr
, q
);
1357 require_noerr( err
, exit
);
1358 obj
->u
.resolve
.txtQuestionActive
= mDNStrue
;
1368 DNSServiceRefDeallocate_direct( obj
);
1374 //===========================================================================================================================
1375 // DNSServiceResolveRelease_direct
1376 //===========================================================================================================================
1378 DEBUG_LOCAL
void DNSServiceResolveRelease_direct( DNSServiceRef inRef
)
1384 if( inRef
->u
.resolve
.srvQuestionActive
)
1386 inRef
->u
.resolve
.srvQuestionActive
= mDNSfalse
;
1387 err
= mDNS_StopQuery( gMDNSPtr
, &inRef
->u
.resolve
.srvQuestion
);
1390 if( inRef
->u
.resolve
.txtQuestionActive
)
1392 inRef
->u
.resolve
.txtQuestionActive
= mDNSfalse
;
1393 err
= mDNS_StopQuery( gMDNSPtr
, &inRef
->u
.resolve
.txtQuestion
);
1399 //===========================================================================================================================
1400 // DNSServiceResolveCallBack_direct
1401 //===========================================================================================================================
1404 DNSServiceResolveCallBack_direct(
1405 mDNS
* const inMDNS
,
1406 DNSQuestion
* inQuestion
,
1407 const ResourceRecord
* const inAnswer
,
1408 mDNSBool inAddRecord
)
1411 const ResourceRecord
** answer
;
1413 char fullName
[ MAX_ESCAPED_DOMAIN_NAME
];
1414 char hostName
[ MAX_ESCAPED_DOMAIN_NAME
];
1419 DEBUG_UNUSED( inMDNS
);
1421 check( inQuestion
);
1422 obj
= (DNSServiceRef
) inQuestion
->QuestionContext
;
1426 // Select the answer based on the type.
1428 if( inAnswer
->rrtype
== kDNSType_SRV
) answer
= &obj
->u
.resolve
.srvAnswer
;
1429 else if( inAnswer
->rrtype
== kDNSType_TXT
) answer
= &obj
->u
.resolve
.txtAnswer
;
1432 dlog( kDebugLevelError
, DEBUG_NAME
"%s: unexpected rrtype (%d)\n", __ROUTINE__
, inAnswer
->rrtype
);
1436 // If the record is being removed, invalidate the previous answer. Otherwise, update with the new answer.
1440 if( *answer
== inAnswer
) *answer
= NULL
;
1445 // Only deliver the result if we have both answers.
1447 if( !obj
->u
.resolve
.srvAnswer
|| !obj
->u
.resolve
.txtAnswer
)
1452 // Convert the results to the appropriate format and call the callback.
1454 ifi
= mDNSPlatformInterfaceIndexfromInterfaceID( &gMDNS
, obj
->u
.resolve
.srvAnswer
->InterfaceID
);
1455 ConvertDomainNameToCString( &obj
->u
.resolve
.srvAnswer
->name
, fullName
);
1456 ConvertDomainNameToCString( &obj
->u
.resolve
.srvAnswer
->rdata
->u
.srv
.target
, hostName
);
1457 port
= obj
->u
.resolve
.srvAnswer
->rdata
->u
.srv
.port
.NotAnInteger
;
1458 txt
= (const char *) obj
->u
.resolve
.txtAnswer
->rdata
->u
.txt
.c
;
1459 txtSize
= obj
->u
.resolve
.txtAnswer
->rdlength
;
1461 obj
->u
.resolve
.callback( obj
, 0, ifi
, kDNSServiceErr_NoError
, fullName
, hostName
, port
, txtSize
, txt
, obj
->context
);
1469 #pragma mark == Special Purpose ==
1472 //===========================================================================================================================
1473 // DNSServiceCreateConnection_direct
1474 //===========================================================================================================================
1476 DNSServiceErrorType
DNSServiceCreateConnection_direct( DNSServiceRef
*outRef
)
1482 require_action( outRef
, exit
, err
= kDNSServiceErr_BadReference
);
1484 // Allocate and initialize the object.
1486 obj
= (DNSServiceRef
) calloc( 1, sizeof( *obj
) );
1487 require_action( obj
, exit
, err
= kNoMemoryErr
);
1489 obj
->releaseCallBack
= DNSServiceCreateConnectionRelease_direct
;
1491 obj
->next
= gDNSServiceRefList
;
1492 gDNSServiceRefList
= obj
;
1504 //===========================================================================================================================
1505 // DNSServiceCreateConnectionRelease_direct
1507 // Warning: Assumes the mDNS platform lock is held.
1508 //===========================================================================================================================
1510 DEBUG_LOCAL
void DNSServiceCreateConnectionRelease_direct( DNSServiceRef inRef
)
1514 while( inRef
->u
.connection
.records
)
1516 DNSRecordRef record
;
1520 record
= inRef
->u
.connection
.records
;
1521 inRef
->u
.connection
.records
= record
->u
.connection
.next
;
1523 // If somebody will be looking at this object next, move the current ptr to the next object.
1525 if( record
== gDNSCurrentRecord
)
1527 dlog( kDebugLevelInfo
, DEBUG_NAME
"deleting gDNSCurrentRecord (%#p)\n", record
);
1528 gDNSCurrentRecord
= record
->u
.connection
.next
;
1531 freeRR
= ( record
->u
.connection
.rr
.resrec
.RecordType
!= kDNSRecordTypeShared
);
1532 err
= mDNS_Deregister( gMDNSPtr
, &record
->u
.connection
.rr
);
1534 if( freeRR
|| ( err
!= mStatus_NoError
) )
1542 //===========================================================================================================================
1543 // DNSServiceConnectionRecordRemove_direct
1545 // Warning: Assumes the mDNS platform lock is held.
1546 //===========================================================================================================================
1548 DEBUG_LOCAL DNSRecordRef
DNSServiceConnectionRecordRemove_direct( DNSServiceRef inRef
, DNSRecordRef inRecordRef
)
1552 for( p
= &inRef
->u
.connection
.records
; *p
; p
= &( *p
)->u
.connection
.next
)
1554 if( *p
== inRecordRef
)
1562 *p
= inRecordRef
->u
.connection
.next
;
1564 // If somebody will be looking at this object next, move the current ptr to the next object.
1566 if( inRecordRef
== gDNSCurrentRecord
)
1568 gDNSCurrentRecord
= inRecordRef
->u
.connection
.next
;
1571 return( inRecordRef
);
1574 //===========================================================================================================================
1575 // DNSServiceRegisterRecord_direct
1576 //===========================================================================================================================
1579 DNSServiceRegisterRecord_direct(
1580 DNSServiceRef inRef
,
1581 DNSRecordRef
* outRecordRef
,
1582 DNSServiceFlags inFlags
,
1583 uint32_t inInterfaceIndex
,
1584 const char * inName
,
1587 uint16_t inRDataSize
,
1588 const void * inRData
,
1590 DNSServiceRegisterRecordReply inCallBack
,
1593 DNSServiceErrorType err
;
1601 require_action( inRef
, exit
, err
= kDNSServiceErr_BadReference
);
1602 require_action( outRecordRef
, exit
, err
= kDNSServiceErr_BadParam
);
1603 require_action( ( inFlags
== kDNSServiceFlagsShared
) ||
1604 ( inFlags
== kDNSServiceFlagsUnique
),
1605 exit
, err
= kDNSServiceErr_BadFlags
);
1606 require_action( inRData
&& ( inRDataSize
> 0 ), exit
, err
= kDNSServiceErr_BadParam
);
1607 require_action( inCallBack
, exit
, err
= kDNSServiceErr_BadParam
);
1609 // Allocate and initialize the record. Allocate oversized record space at the end of the record.
1611 size
= ( inRDataSize
> sizeof( RDataBody
) ) ? inRDataSize
: sizeof( RDataBody
);
1612 obj
= (DNSRecordRef
) calloc( 1, ( kDNSRecordConnectionFixedSize
- sizeof( RDataBody
) ) + size
);
1613 require_action( obj
, exit
, err
= kDNSServiceErr_NoMemory
);
1615 obj
->u
.connection
.owner
= inRef
;
1616 obj
->u
.connection
.callback
= inCallBack
;
1617 obj
->u
.connection
.context
= inContext
;
1619 obj
->u
.connection
.next
= inRef
->u
.connection
.records
;
1620 inRef
->u
.connection
.records
= obj
;
1622 rr
= &obj
->u
.connection
.rr
;
1623 rr
->resrec
.RecordType
= (mDNSu8
)( ( inFlags
== kDNSServiceFlagsShared
) ? kDNSRecordTypeShared
: kDNSRecordTypeUnique
);
1624 rr
->resrec
.InterfaceID
= mDNSPlatformInterfaceIDfromInterfaceIndex( gMDNSPtr
, inInterfaceIndex
);
1626 ok
= MakeDomainNameFromDNSNameString( &rr
->resrec
.name
, inName
) != NULL
;
1627 require_action( ok
, exit
, err
= kDNSServiceErr_BadParam
);
1629 rr
->resrec
.rrtype
= inRRType
;
1630 rr
->resrec
.rrclass
= inRRClass
;
1631 rr
->resrec
.rroriginalttl
= inTTL
;
1632 rr
->resrec
.rdlength
= inRDataSize
;
1633 rr
->resrec
.rdata
= &rr
->rdatastorage
;
1634 rr
->resrec
.rdata
->MaxRDLength
= inRDataSize
;
1635 memcpy( rr
->resrec
.rdata
->u
.data
, inRData
, inRDataSize
);
1636 rr
->RecordContext
= obj
;
1637 rr
->RecordCallback
= DNSServiceRegisterRecordCallBack_direct
;
1639 // Register the record with mDNS.
1641 err
= mDNS_Register( gMDNSPtr
, rr
);
1642 require_noerr( err
, exit
);
1646 *outRecordRef
= obj
;
1652 DNSServiceConnectionRecordRemove_direct( inRef
, obj
);
1659 //===========================================================================================================================
1660 // DNSServiceRegisterRecord_direct
1662 // Warning: Assumes the mDNS platform lock is held (held by mDNS before invoking this callback).
1663 //===========================================================================================================================
1665 DEBUG_LOCAL
void DNSServiceRegisterRecordCallBack_direct( mDNS
* const inMDNS
, AuthRecord
* const inRR
, mStatus inResult
)
1669 DEBUG_UNUSED( inMDNS
);
1672 obj
= (DNSRecordRef
) inRR
->RecordContext
;
1675 if( inResult
== mStatus_MemFree
)
1677 DNSServiceConnectionRecordRemove_direct( obj
->u
.connection
.owner
, obj
);
1682 obj
->u
.connection
.callback( obj
->u
.connection
.owner
, obj
, 0, inResult
, obj
->u
.connection
.context
);
1686 //===========================================================================================================================
1687 // DNSServiceQueryRecord_direct
1688 //===========================================================================================================================
1691 DNSServiceQueryRecord_direct(
1692 DNSServiceRef
* outRef
,
1693 DNSServiceFlags inFlags
,
1694 uint32_t inInterfaceIndex
,
1695 const char * inName
,
1698 DNSServiceQueryRecordReply inCallBack
,
1701 DNSServiceErrorType err
;
1708 require_action( outRef
, exit
, err
= kDNSServiceErr_BadParam
);
1709 require_action( inFlags
== 0, exit
, err
= kDNSServiceErr_BadFlags
);
1710 require_action( inName
, exit
, err
= kDNSServiceErr_BadParam
);
1711 require_action( inCallBack
, exit
, err
= kDNSServiceErr_BadParam
);
1713 // Allocate and initialize the object.
1715 obj
= (DNSServiceRef
) calloc( 1, sizeof( *obj
) );
1716 require_action( obj
, exit
, err
= kDNSServiceErr_NoMemory
);
1718 obj
->releaseCallBack
= DNSServiceQueryRecordRelease_direct
;
1719 obj
->context
= inContext
;
1720 obj
->u
.query
.callback
= inCallBack
;
1722 q
= &obj
->u
.query
.question
;
1723 q
->InterfaceID
= mDNSPlatformInterfaceIDfromInterfaceIndex( gMDNSPtr
, inInterfaceIndex
);
1724 ok
= MakeDomainNameFromDNSNameString( &q
->qname
, inName
) != NULL
;
1725 require_action( ok
, exit
, err
= kDNSServiceErr_BadParam
);
1726 q
->qtype
= inRRType
;
1727 q
->qclass
= inRRClass
;
1728 q
->QuestionCallback
= DNSServiceQueryRecordCallBack_direct
;
1729 q
->QuestionContext
= obj
;
1731 obj
->next
= gDNSServiceRefList
;
1732 gDNSServiceRefList
= obj
;
1734 // Start the query with mDNS.
1736 err
= mDNS_StartQuery( gMDNSPtr
, q
);
1737 require_noerr( err
, exit
);
1738 obj
->u
.query
.questionActive
= mDNStrue
;
1748 DNSServiceRefDeallocate_direct( obj
);
1754 //===========================================================================================================================
1755 // DNSServiceQueryRecordRelease_direct
1757 // Warning: Assumes the mDNS platform lock is held.
1758 //===========================================================================================================================
1760 DEBUG_LOCAL
void DNSServiceQueryRecordRelease_direct( DNSServiceRef inRef
)
1766 if( inRef
->u
.query
.questionActive
)
1768 err
= mDNS_StopQuery( gMDNSPtr
, &inRef
->u
.query
.question
);
1774 //===========================================================================================================================
1775 // DNSServiceQueryRecordCallBack_direct
1777 // Warning: Assumes the mDNS platform lock is held (held by mDNS before invoking this callback).
1778 //===========================================================================================================================
1781 DNSServiceQueryRecordCallBack_direct(
1782 mDNS
* const inMDNS
,
1783 DNSQuestion
* inQuestion
,
1784 const ResourceRecord
* const inAnswer
,
1785 mDNSBool inAddRecord
)
1788 DNSServiceFlags flags
;
1789 uint32_t interfaceIndex
;
1790 char name
[ MAX_ESCAPED_DOMAIN_NAME
];
1792 DEBUG_UNUSED( inMDNS
);
1794 check( inQuestion
);
1795 obj
= (DNSServiceRef
) inQuestion
->QuestionContext
;
1799 flags
= inAddRecord
? kDNSServiceFlagsAdd
: kDNSServiceFlagsNone
;
1800 interfaceIndex
= mDNSPlatformInterfaceIndexfromInterfaceID( &gMDNS
, inAnswer
->InterfaceID
);
1801 ConvertDomainNameToCString( &inAnswer
->name
, name
);
1802 obj
->u
.query
.callback( obj
, flags
, interfaceIndex
, kDNSServiceErr_NoError
, name
, inAnswer
->rrtype
, inAnswer
->rrclass
,
1803 inAnswer
->rdlength
, &inAnswer
->rdata
->u
, inAddRecord
? inAnswer
->rroriginalttl
: 0, obj
->context
);
1806 //===========================================================================================================================
1807 // DNSServiceReconfirmRecord_direct
1808 //===========================================================================================================================
1811 DNSServiceReconfirmRecord_direct(
1812 DNSServiceFlags inFlags
,
1813 uint32_t inInterfaceIndex
,
1814 const char * inName
,
1817 uint16_t inRDataSize
,
1818 const void * inRData
)
1820 DNSServiceErrorType err
;
1827 require_action( inFlags
== 0, exit
, err
= kDNSServiceErr_BadFlags
);
1828 require_action( inName
, exit
, err
= kDNSServiceErr_BadParam
);
1829 require_action( inRData
&& ( inRDataSize
> 0 ), exit
, err
= kDNSServiceErr_BadParam
);
1831 size
= ( inRDataSize
> sizeof( RDataBody
) ) ? inRDataSize
: sizeof( RDataBody
);
1832 rr
= (AuthRecord
*) calloc( 1, ( sizeof( *rr
) - sizeof( RDataBody
) ) + size
);
1833 require_action( rr
, exit
, err
= kDNSServiceErr_NoMemory
);
1835 rr
->resrec
.RecordType
= (mDNSu8
)( ( inFlags
== kDNSServiceFlagsShared
) ? kDNSRecordTypeShared
: kDNSRecordTypeUnique
);
1836 rr
->resrec
.InterfaceID
= mDNSPlatformInterfaceIDfromInterfaceIndex( gMDNSPtr
, inInterfaceIndex
);
1838 ok
= MakeDomainNameFromDNSNameString( &rr
->resrec
.name
, inName
) != NULL
;
1839 require_action( ok
, exit
, err
= kDNSServiceErr_BadParam
);
1841 rr
->resrec
.rrtype
= inRRType
;
1842 rr
->resrec
.rrclass
= inRRClass
;
1843 rr
->resrec
.rdlength
= inRDataSize
;
1844 rr
->resrec
.rdata
= &rr
->rdatastorage
;
1845 rr
->resrec
.rdata
->MaxRDLength
= inRDataSize
;
1846 memcpy( rr
->resrec
.rdata
->u
.data
, inRData
, inRDataSize
);
1848 err
= mDNS_ReconfirmByValue( gMDNSPtr
, &rr
->resrec
);
1849 check( ( err
== mStatus_BadReferenceErr
) || ( err
== mStatus_NoError
) );
1863 #endif // DNS_SD_DIRECT_ENABLED