1 /*
2  * Copyright (c) 2019-2020 Apple Inc. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     https://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef __MDNS_OBJECT_H__
18 #define __MDNS_OBJECT_H__
19 
20 #include "mdns_base.h"
21 
22 #include <CoreFoundation/CoreFoundation.h>
23 
24 /*!
25  *	@brief
26  *		CFArray callbacks for mdns objects.
27  */
28 extern const CFArrayCallBacks mdns_cfarray_callbacks;
29 
30 MDNS_ASSUME_NONNULL_BEGIN
31 
32 /*!
33  *	@typedef	mdns_any_t
34  *	@brief
35  *		A pointer to an mdns object.
36  */
37 #if OS_OBJECT_USE_OBJC
38 	typedef mdns_object_t	mdns_any_t;
39 #else
40 	#if defined(__cplusplus)
41 		typedef void *	mdns_any_t;
42 	#else
43 		#if !defined(MDNS_ANY_TYPE_INTERNAL_MEMBERS)
44 			#define MDNS_ANY_TYPE_INTERNAL_MEMBERS
45 		#endif
46 		typedef union {
47 			MDNS_UNION_MEMBER(object);
48 			MDNS_UNION_MEMBER(address);
49 			MDNS_UNION_MEMBER(dns_service);
50 			MDNS_UNION_MEMBER(dns_service_manager);
51 			MDNS_UNION_MEMBER(interface_monitor);
52 			MDNS_UNION_MEMBER(message);
53 			MDNS_UNION_MEMBER(query_message);
54 			MDNS_UNION_MEMBER(querier);
55 			MDNS_UNION_MEMBER(resolver);
56 			MDNS_UNION_MEMBER(set);
57 			MDNS_UNION_MEMBER(trust);
58 			MDNS_ANY_TYPE_INTERNAL_MEMBERS
59 		} mdns_any_t __attribute__((__transparent_union__));
60 	#endif
61 #endif
62 
63 __BEGIN_DECLS
64 
65 /*!
66  *	@brief
67  *		Increments the reference count of an mdns object.
68  *
69  *	@param object
70  *		The mdns object.
71  */
72 mdns_object_t
73 mdns_retain(mdns_any_t object);
74 #if OS_OBJECT_USE_OBJC_RETAIN_RELEASE
75 	#undef mdns_retain
76 	#define mdns_retain(object)	[(object) retain]
77 #endif
78 
79 /*!
80  *	@brief
81  *		Decrements the reference count of an mdns object.
82  *
83  *	@param object
84  *		The mdns object.
85  */
86 void
87 mdns_release(mdns_any_t object);
88 #if OS_OBJECT_USE_OBJC_RETAIN_RELEASE
89 	#undef mdns_release
90 	#define mdns_release(object)	[(object) release]
91 #endif
92 
93 /*!
94  *	@brief
95  *		Creates a human-readable description of an mdns object as a C string encoded in UTF-8.
96  *
97  *	@param object
98  *		The mdns object.
99  *
100  *	@result
101  *		A C string that must be freed with free(3).
102  */
103 MDNS_WARN_RESULT
104 char * _Nullable
105 mdns_copy_description(mdns_any_t object);
106 
107 /*!
108  *	@brief
109  *		Determines whether two mdns objects are equal.
110  *
111  *	@param object1
112  *		The first object.
113  *
114  *	@param object2
115  *		The second object.
116  *
117  *	@result
118  *		Returns true if the two objects are equal, otherwise false.
119  */
120 bool
121 mdns_equal(mdns_any_t object1, mdns_any_t object2);
122 
123 /*!
124  *	@brief
125  *		Generic events that may occur during the lifetime of some mdns objects.
126  *
127  *	@const mdns_event_error
128  *		A fatal error has occurred.
129  *
130  *	@const mdns_event_invalidated
131  *		The object has been invalidated.
132  *
133  *	@const mdns_event_update
134  *		Some aspect of the object has been updated.
135  */
136 OS_CLOSED_ENUM(mdns_event, int,
137 	mdns_event_error		= 1,
138 	mdns_event_invalidated	= 2,
139 	mdns_event_update		= 3
140 );
141 
142 static inline const char *
mdns_event_to_string(mdns_event_t event)143 mdns_event_to_string(mdns_event_t event)
144 {
145 	switch (event) {
146 		case mdns_event_error:			return "Error";
147 		case mdns_event_invalidated:	return "Invalidated";
148 		default:						return "?";
149 	}
150 }
151 
152 /*!
153  *	@brief
154  *		Generic event handler for mdns objects.
155  *
156  *	@param event
157  *		The event.
158  *
159  *	@param error
160  *		The error associated with a <code>mdns_event_error</code> event. This argument should be ignored for all
161  *		other types of events.
162  *
163  *	@discussion
164  *		After an <code>mdns_event_invalidated</code> event, none of the object's handlers will ever be invoked again.
165  */
166 typedef void (^mdns_event_handler_t)(mdns_event_t event, OSStatus error);
167 
168 __END_DECLS
169 
170 MDNS_ASSUME_NONNULL_END
171 
172 #if OS_OBJECT_USE_OBJC && __has_feature(objc_arc)
173 	#define mdns_retain_arc_safe(OBJ)	(OBJ)
174 	#define mdns_release_arc_safe(OBJ)	do {} while (0)
175 #else
176 	#define mdns_retain_arc_safe(OBJ)	mdns_retain(OBJ)
177 	#define mdns_release_arc_safe(OBJ)	mdns_release(OBJ)
178 #endif
179 
180 #define mdns_retain_null_safe(OBJ)		\
181 	do {								\
182 		if (OBJ) {						\
183 			mdns_retain_arc_safe(OBJ);	\
184 		}								\
185 	} while (0)							\
186 
187 #define mdns_release_null_safe(OBJ)		\
188 	do {								\
189 		if (OBJ) {						\
190 			mdns_release_arc_safe(OBJ);	\
191 		}								\
192 	} while (0)							\
193 
194 #define mdns_forget(PTR)					\
195 	do {									\
196 		if (*(PTR)) {						\
197 			mdns_release_arc_safe(*(PTR));	\
198 			*(PTR) = NULL;					\
199 		}									\
200 	} while(0)
201 
202 #define mdns_replace(PTR, OBJ)				\
203 	do {									\
204 		if (OBJ) {							\
205 			mdns_retain_arc_safe(OBJ);		\
206 		}									\
207 		if (*(PTR)) {						\
208 			mdns_release_arc_safe(*(PTR));	\
209 		}									\
210 		*(PTR) = (OBJ);						\
211 	} while(0)
212 
213 #endif	// __MDNS_OBJECT_H__
214