master
  1#ifndef __XPC_SESSION_H__
  2#define __XPC_SESSION_H__
  3
  4#ifndef __XPC_INDIRECT__
  5#error "Please #include <xpc/xpc.h> instead of this file directly."
  6// For HeaderDoc.
  7#include <xpc/base.h>
  8#endif // __XPC_INDIRECT__
  9
 10#ifndef __BLOCKS__
 11#error "XPC Session require Blocks support."
 12#endif // __BLOCKS__
 13
 14XPC_ASSUME_NONNULL_BEGIN
 15__BEGIN_DECLS
 16
 17/*!
 18 * @define XPC_TYPE_SESSION
 19 *
 20 * @discussion
 21 * Sessions represent a stateful connection between a client and a service. When either end of the connection
 22 * disconnects, the entire session will be invalidated. In this case the system will make no attempt to
 23 * reestablish the connection or relaunch the service.
 24 *
 25 * Clients can initiate a session with a service that accepts xpc_connection_t connections but session
 26 * semantics will be maintained.
 27 *
 28 * Sessions can be created in an active or inactive state. They must be
 29 * activated and subsequently cancelled before they can be released.
 30 *
 31 */
 32OS_OBJECT_DECL_SENDABLE_CLASS(xpc_session);
 33
 34#pragma mark Constants
 35/*!
 36 * @typedef xpc_session_create_flags_t
 37 * Constants representing different options available when creating an XPC
 38 * Session.
 39 *
 40 * @const XPC_SESSION_CREATE_INACTIVE
 41 * Indicates that the session should not be activated during its creation. The
 42 * returned session must be manually activated using
 43 * {@link xpc_session_activate} before it can be used.
 44 *
 45 * @const XPC_SESSION_CREATE_MACH_PRIVILEGED
 46 * Passed to {@link xpc_session_create_mach_service} to indicate that the job
 47 * advertising the service name in its launchd.plist(5) should be in the
 48 * privileged Mach bootstrap. This is typically accomplished by placing your
 49 * launchd.plist(5) in /Library/LaunchDaemons.
 50 */
 51XPC_SWIFT_NOEXPORT
 52XPC_FLAGS_ENUM(xpc_session_create_flags, uint64_t,
 53	XPC_SESSION_CREATE_NONE XPC_SWIFT_NAME("none") = 0,
 54	XPC_SESSION_CREATE_INACTIVE XPC_SWIFT_NAME("inactive") = (1 << 0),
 55	XPC_SESSION_CREATE_MACH_PRIVILEGED XPC_SWIFT_NAME("privileged") = (1 << 1)
 56);
 57
 58#pragma mark Handlers
 59typedef void (^xpc_session_cancel_handler_t)(xpc_rich_error_t error) XPC_SWIFT_NOEXPORT;
 60typedef void (^xpc_session_incoming_message_handler_t)(xpc_object_t message) XPC_SWIFT_NOEXPORT;
 61typedef void (^xpc_session_reply_handler_t)(xpc_object_t _Nullable reply,
 62		xpc_rich_error_t _Nullable error) XPC_SWIFT_NOEXPORT;
 63
 64#pragma mark Helpers
 65/*!
 66 * @function xpc_session_copy_description
 67 * Copy the string description of the session.
 68 *
 69 * @param session
 70 * The session to be examined.
 71 *
 72 * @result
 73 * The underlying C string description for the provided session. This string
 74 * should be disposed of with free(3) when done. This will return NULL if a
 75 * string description could not be generated.
 76 */
 77API_AVAILABLE(macos(13.0), ios(16.0), tvos(16.0), watchos(9.0))
 78XPC_EXPORT XPC_SWIFT_NOEXPORT XPC_WARN_RESULT
 79char * _Nullable
 80xpc_session_copy_description(xpc_session_t session);
 81
 82#pragma mark Client Session Creation
 83/*!
 84 * @function xpc_session_create_xpc_service
 85 * Creates a new session object representing a connection to the named service.
 86 *
 87 * @param name
 88 * The name of the service to create a session with.
 89 *
 90 * @param target_queue
 91 * The GCD queue onto which session events will be submitted. This may be a
 92 * concurrent queue. This parameter may be NULL, in which case the target queue
 93 * will be libdispatch's default target queue, defined as
 94 * DISPATCH_TARGET_QUEUE_DEFAULT.
 95 *
 96 * @param flags
 97 * Additional attributes which which to create the session.
 98 *
 99 * @param error_out
100 * An out-parameter that, if set and in the event of an error, will point to an
101 * {@link xpc_rich_error_t} describing the details of any errors that occurred.
102 *
103 * @result
104 * On success this returns a new session object. The returned session is
105 * activated by default and can be used to send messages. The caller is
106 * responsible for disposing of the returned object with {@link xpc_release}
107 * when it is no longer needed. On failure this will return NULL and if set,
108 * error_out will be set to an error describing the failure.
109 *
110 * @discussion
111 * This will fail if the specified XPC service is either not found or is
112 * unavailable.
113 */
114API_AVAILABLE(macos(13.0), macCatalyst(16.0))
115API_UNAVAILABLE(ios, tvos, watchos)
116XPC_EXPORT XPC_SWIFT_NOEXPORT XPC_RETURNS_RETAINED XPC_WARN_RESULT
117xpc_session_t _Nullable
118xpc_session_create_xpc_service(const char *name,
119		dispatch_queue_t _Nullable target_queue,
120		xpc_session_create_flags_t flags,
121		xpc_rich_error_t _Nullable * _Nullable error_out);
122
123/*!
124 * @function xpc_session_create_mach_service
125 * Creates a session with the service defined by the provided Mach service name.
126 *
127 * @param mach_service
128 * The Mach service to create a session with. The service name must exist in the
129 * Mach bootstrap that is accessible to the process and be advertised in a
130 * launchd.plist.
131 *
132 * @param target_queue
133 * The GCD queue onto which session events will be submitted. This may be a
134 * concurrent queue. This parameter may be NULL, in which case the target queue
135 * will be libdispatch's default target queue, defined as
136 * DISPATCH_TARGET_QUEUE_DEFAULT.
137 *
138 * @param flags
139 * Additional attributes which which to create the session.
140 *
141 * @param error_out
142 * An out-parameter that, if set and in the event of an error, will point to an
143 * {@link xpc_rich_error_t} describing the details of any errors that occurred.
144 *
145 * @result
146 * On success this returns a new session object. The returned session is
147 * activated by default and can be used to send messages. The caller is
148 * responsible for disposing of the returned object with {@link xpc_release}
149 * when it is no longer needed. On failure this will return NULL and if set,
150 * error_out will be set to an error describing the failure.
151 *
152 * @discussion
153 * This will fail if the specified Mach service is either not found in the
154 * bootstrap or is otherwise unavailable.
155 *
156 */
157API_AVAILABLE(macos(13.0), macCatalyst(16.0))
158API_UNAVAILABLE(ios, tvos, watchos)
159XPC_EXPORT XPC_SWIFT_NOEXPORT XPC_RETURNS_RETAINED XPC_WARN_RESULT
160xpc_session_t _Nullable
161xpc_session_create_mach_service(const char *mach_service,
162		dispatch_queue_t _Nullable target_queue,
163		xpc_session_create_flags_t flags,
164		xpc_rich_error_t _Nullable * _Nullable error_out);
165
166#pragma mark Session Configuration
167/*!
168 * @function xpc_session_set_incoming_message_handler
169 * Set an incoming message handler for a session.
170 *
171 * @param session
172 * The session to set the handler for.
173 *
174 * @param handler
175 * The handler block to be called when a message originated by the peer is
176 * received through the provided session.
177 *
178 * @discussion
179 * This can only be called on an inactive session. Calling this on a session
180 * with an existing event handler will replace it.
181 */
182API_AVAILABLE(macos(13.0), ios(16.0), tvos(16.0), watchos(9.0))
183XPC_EXPORT XPC_SWIFT_NOEXPORT
184void
185xpc_session_set_incoming_message_handler(xpc_session_t session,
186		xpc_session_incoming_message_handler_t handler);
187
188/*!
189 * @function xpc_session_set_cancel_handler
190 * Set the cancel handler for a session.
191 *
192 * @param session
193 * The session to set the cancel handler for.
194 *
195 * @param cancel_handler
196 * The cancel handler block that will be executed when this session is canceled.
197 *
198 * @discussion
199 * This can only be called on an inactive session. Calling this on a session
200 * with an existing cancel handler will replace the existing cancel handler with
201 * the one provided.
202 */
203API_AVAILABLE(macos(13.0), ios(16.0), tvos(16.0), watchos(9.0))
204XPC_EXPORT XPC_SWIFT_NOEXPORT
205void
206xpc_session_set_cancel_handler(xpc_session_t session,
207		xpc_session_cancel_handler_t cancel_handler);
208
209/*!
210 * @function xpc_session_set_target_queue
211 * Set the target queue for a session.
212 *
213 * @param session
214 * The session to set the target queue for.
215 *
216 * @param target_queue
217 * The GCD queue onto which session events will be submitted. This may be a
218 * concurrent queue. This parameter may be NULL, in which case the target queue
219 * will be libdispatch's default target queue, defined as
220 * DISPATCH_TARGET_QUEUE_DEFAULT.
221 *
222 * @discussion
223 * This can only be called on an inactive session. Calling this on a session
224 * with an existing target queue will replace the existing target queue with
225 * the one provided.
226 */
227API_AVAILABLE(macos(14.0), ios(17.0), tvos(17.0), watchos(10.0))
228XPC_EXPORT XPC_SWIFT_NOEXPORT
229void
230xpc_session_set_target_queue(xpc_session_t session,
231		dispatch_queue_t _Nullable target_queue);
232
233#pragma mark Lifecycle
234/*!
235 * @function xpc_session_activate
236 * Activates a session.
237 *
238 * @param session
239 * The session object to activate.
240 *
241 * @param error_out
242 * An out-parameter that, if set and in the event of an error, will point to an
243 * {@link xpc_rich_error_t} describing the details of any errors that occurred.
244 *
245 * @result
246 * Returns whether session activation succeeded.
247 *
248 * @discussion
249 * xpc_session_activate must not be called on a session that has been already
250 * activated. Releasing the last reference on an inactive session or an
251 * active session that has not been cancelled will trigger an API misuse crash.
252 *
253 * If activation fails, the session is automatically cancelled. 
254 */
255API_AVAILABLE(macos(13.0), ios(16.0), tvos(16.0), watchos(9.0))
256XPC_EXPORT XPC_SWIFT_NOEXPORT
257bool
258xpc_session_activate(xpc_session_t session,
259		xpc_rich_error_t _Nullable * _Nullable error_out);
260
261/*!
262 * @function xpc_session_cancel
263 * Cancels the session. After this call, any messages that have not yet been
264 * sent will be discarded, and the connection will be unwound. If there are
265 * messages that are awaiting replies, they will have their reply handlers
266 * invoked with an appropriate {@link xpc_rich_error_t}.
267 *
268 * @param session
269 * The session object to cancel.
270 *
271 * @discussion
272 * Session must have been activated to be cancelled and must be cancelled
273 * before the last reference can be released. Cancellation is asynchronous and
274 * non-preemptive.
275 */
276API_AVAILABLE(macos(13.0), ios(16.0), tvos(16.0), watchos(9.0))
277XPC_EXPORT XPC_SWIFT_NOEXPORT
278void
279xpc_session_cancel(xpc_session_t session);
280
281#pragma mark Message Send
282/*!
283 * @function xpc_session_send_message
284 * Sends a message over the session to the destination service.
285 *
286 * @param session
287 * The session to send the message over.
288 *
289 * @param message
290 * The message to send. This must be a dictionary object.
291 *
292 * @result
293 * In the event of an error this will return an {@link xpc_rich_error_t}
294 * detailing the reasons for the failure. On success this return value will be
295 * NULL.
296 *
297 * @discussion
298 * Messages are delivered in FIFO order. This API is safe to call from multiple
299 * GCD queues. There is no indication that a message was delivered successfully.
300 * This is because even once the message has been successfully enqueued on the
301 * remote end, there are no guarantees about when the runtime will dequeue the
302 * message and invoke the other session's event handler block.
303 *
304 * If this is invoked on an inactive session, one created using the
305 * XPC_SESSION_CREATE_INACTIVE flag and hasn't yet been activated, the process
306 * will crash.
307 */
308API_AVAILABLE(macos(13.0), ios(16.0), tvos(16.0), watchos(9.0))
309XPC_EXPORT XPC_SWIFT_NOEXPORT XPC_RETURNS_RETAINED XPC_WARN_RESULT
310xpc_rich_error_t _Nullable
311xpc_session_send_message(xpc_session_t session, xpc_object_t message);
312
313/*!
314 * @function xpc_session_send_message_with_reply_sync
315 * Sends a message over the session to the destination service and blocks the
316 * caller until a reply is received.
317 *
318 * @param session
319 * The session over which the message will be sent.
320 *
321 * @param message
322 * The message to send. This must be a dictionary object.
323 *
324 * @param error_out
325 * If this parameter is provided, in the event of a failure it will point to an
326 * {@link xpc_rich_error_t} describing the details of the error.
327 *
328 * @result
329 * On success, this will return the reply message as an {@link xpc_object_t}.
330 * Otherwise NULL is returned.
331 *
332 * @discussion
333 * This API supports priority inversion avoidance and should be used instead of
334 * combining xpc_session_send_message_with_reply_async with a semaphore.
335 *
336 * If this is invoked on an inactive session, for example one created using the
337 * XPC_SESSION_CREATE_INACTIVE flag that hasn't yet been activated, the process
338 * will crash.
339 * 
340 * Invoking this API while the target queue is blocked would lead to deadlocks
341 * in certain scenarios. For that reason, invoking it from the target queue
342 * results in a crash.
343 *
344 * Be judicious about your use of this API. It can block indefinitely, so if you
345 * are using it to implement an API that can be called from the main queue, you
346 * may wish to consider allowing the API to take a queue and callback block so
347 * that results may be delivered asynchronously if possible.
348 */
349API_AVAILABLE(macos(13.0), ios(16.0), tvos(16.0), watchos(9.0))
350XPC_EXPORT XPC_SWIFT_NOEXPORT XPC_RETURNS_RETAINED XPC_WARN_RESULT
351xpc_object_t _Nullable
352xpc_session_send_message_with_reply_sync(xpc_session_t session,
353		xpc_object_t message, xpc_rich_error_t _Nullable * _Nullable error_out);
354
355/*!
356 * @function xpc_session_send_message_with_reply_async
357 * Sends a message over the session to the destination service and executes the
358 * provided callback when a reply is received.
359 *
360 * @param session
361 * The session over which the message will be sent.
362 *
363 * @param message
364 * The message to send. This must be a dictionary object.
365 *
366 * @param reply_handler
367 * The handler block to invoke when a reply to the message is received from the
368 * session. If the session is torn down before the reply was received, for
369 * example if the remote service exits prematurely, this handler will be
370 * executed and passed an appropriate {@link xpc_rich_error_t} object describing
371 * the failure.
372 *
373 * @discussion
374 * If this is invoked on an inactive session, for example one created using the
375 * XPC_SESSION_CREATE_INACTIVE flag that hasn't yet been activated, the process
376 * will crash.
377 *
378 * If this is invoked on a cancelled session, this will generate a simulated
379 * crash.
380 */
381API_AVAILABLE(macos(13.0), ios(16.0), tvos(16.0), watchos(9.0))
382XPC_EXPORT XPC_SWIFT_NOEXPORT
383void
384xpc_session_send_message_with_reply_async(xpc_session_t session,
385		xpc_object_t message, xpc_session_reply_handler_t reply_handler);
386
387/*!
388 * @function xpc_session_set_peer_code_signing_requirement
389 * Requires that the session peer satisfies a code signing requirement.
390 *
391 * @param session
392 * The session object which is to be modified.
393 *
394 * @param requirement
395 * The code signing requirement to be satisfied by the peer. It is safe to
396 * deallocate the requirement string after calling this function.
397 *
398 * @result
399 * 0 on success, non-zero on error
400 *
401 * @discussion
402 * This function will return an error promptly if the code signing requirement
403 * string is invalid.
404 *
405 * It is a programming error to call `xpc_session_set_peer_*requirement` more
406 * than once per session.
407 *
408 * All messages received on this session will be checked to ensure they come
409 * from a peer who satisfies the code signing requirement. When message or a
410 * reply is received on the session and the peer does not satisfy the
411 * requirement the session will be cancelled. A rich error describing the peer
412 * code signing error will be passed to the cancellation handler. For
413 * `xpc_session_send_message_with_reply_*` NULL will be returned instead of
414 * reply, with `error_out` pointing to that rich error.
415 *
416 * @see https://developer.apple.com/documentation/technotes/tn3127-inside-code-signing-requirements
417 */
418API_AVAILABLE(macos(14.4))
419API_UNAVAILABLE(ios, tvos, watchos)
420XPC_EXPORT XPC_NONNULL_ALL XPC_WARN_RESULT
421int
422xpc_session_set_peer_code_signing_requirement(xpc_session_t session, const char *requirement);
423
424/*!
425 * @function xpc_session_set_peer_requirement
426 * Requires that the session peer satisfies a requirement.
427 *
428 * @param session
429 * The session object which is to be modified. Must be inactive.
430 *
431 * @param requirement
432 * The requirement to be satisfied by the peer. It will be retained by XPC.
433 *
434 * @discussion
435 * It is a programming error to call `xpc_session_set_peer_*requirement` more
436 * than once per session.
437 *
438 * All messages received on this session will be checked to ensure they come
439 * from a peer who satisfies the requirement. When a reply is expected on the
440 * session and the peer does not satisfy the requirement, the session will be
441 * canceled with cancellation handler called with a rich error describing the
442 * peer code signing error. For `xpc_session_send_message_with_reply_sync` NULL
443 * will be returned instead of reply, with `error_out` (if set) pointing to the
444 * rich error describing the peer code signing error.
445 */
446API_AVAILABLE(macos(26.0), ios(26.0))
447API_UNAVAILABLE(tvos, watchos)
448XPC_EXPORT XPC_SWIFT_NOEXPORT XPC_NONNULL_ALL
449void
450xpc_session_set_peer_requirement(xpc_session_t session, xpc_peer_requirement_t requirement);
451
452/* This is included for compatibility and should not be used in new code */
453#define XPC_TYPE_SESSION (&_xpc_type_session)
454XPC_EXPORT
455XPC_TYPE(_xpc_type_session);
456
457__END_DECLS
458XPC_ASSUME_NONNULL_END
459
460#endif // __XPC_SESSION_H__