| 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 | |
| 14 | XPC_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 | */ |
| 32 | OS_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 | */ |
| 51 | XPC_SWIFT_NOEXPORT |
| 52 | XPC_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 |
| 59 | typedef void (^xpc_session_cancel_handler_t)(xpc_rich_error_t error) XPC_SWIFT_NOEXPORT; |
| 60 | typedef void (^xpc_session_incoming_message_handler_t)(xpc_object_t message) XPC_SWIFT_NOEXPORT; |
| 61 | typedef 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 | */ |
| 77 | API_AVAILABLE(macos(13.0), ios(16.0), tvos(16.0), watchos(9.0)) |
| 78 | XPC_EXPORT XPC_SWIFT_NOEXPORT XPC_WARN_RESULT |
| 79 | char * _Nullable |
| 80 | xpc_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 | */ |
| 114 | API_AVAILABLE(macos(13.0), macCatalyst(16.0)) |
| 115 | API_UNAVAILABLE(ios, tvos, watchos) |
| 116 | XPC_EXPORT XPC_SWIFT_NOEXPORT XPC_RETURNS_RETAINED XPC_WARN_RESULT |
| 117 | xpc_session_t _Nullable |
| 118 | xpc_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 XPC_GIVES_REFERENCE * _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 | */ |
| 157 | API_AVAILABLE(macos(13.0), macCatalyst(16.0)) |
| 158 | API_UNAVAILABLE(ios, tvos, watchos) |
| 159 | XPC_EXPORT XPC_SWIFT_NOEXPORT XPC_RETURNS_RETAINED XPC_WARN_RESULT |
| 160 | xpc_session_t _Nullable |
| 161 | xpc_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 XPC_GIVES_REFERENCE * _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 | */ |
| 182 | API_AVAILABLE(macos(13.0), ios(16.0), tvos(16.0), watchos(9.0)) |
| 183 | XPC_EXPORT XPC_SWIFT_NOEXPORT |
| 184 | void |
| 185 | xpc_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 | */ |
| 203 | API_AVAILABLE(macos(13.0), ios(16.0), tvos(16.0), watchos(9.0)) |
| 204 | XPC_EXPORT XPC_SWIFT_NOEXPORT |
| 205 | void |
| 206 | xpc_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 | */ |
| 227 | API_AVAILABLE(macos(14.0), ios(17.0), tvos(17.0), watchos(10.0)) |
| 228 | XPC_EXPORT XPC_SWIFT_NOEXPORT |
| 229 | void |
| 230 | xpc_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 | */ |
| 255 | API_AVAILABLE(macos(13.0), ios(16.0), tvos(16.0), watchos(9.0)) |
| 256 | XPC_EXPORT XPC_SWIFT_NOEXPORT |
| 257 | bool |
| 258 | xpc_session_activate(xpc_session_t session, |
| 259 | 		xpc_rich_error_t _Nullable XPC_GIVES_REFERENCE * _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 | */ |
| 276 | API_AVAILABLE(macos(13.0), ios(16.0), tvos(16.0), watchos(9.0)) |
| 277 | XPC_EXPORT XPC_SWIFT_NOEXPORT |
| 278 | void |
| 279 | xpc_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 | */ |
| 308 | API_AVAILABLE(macos(13.0), ios(16.0), tvos(16.0), watchos(9.0)) |
| 309 | XPC_EXPORT XPC_SWIFT_NOEXPORT XPC_RETURNS_RETAINED XPC_WARN_RESULT |
| 310 | xpc_rich_error_t _Nullable |
| 311 | xpc_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 | */ |
| 349 | API_AVAILABLE(macos(13.0), ios(16.0), tvos(16.0), watchos(9.0)) |
| 350 | XPC_EXPORT XPC_SWIFT_NOEXPORT XPC_RETURNS_RETAINED XPC_WARN_RESULT |
| 351 | xpc_object_t _Nullable |
| 352 | xpc_session_send_message_with_reply_sync(xpc_session_t session, |
| 353 | 		xpc_object_t message, xpc_rich_error_t _Nullable XPC_GIVES_REFERENCE * _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 | */ |
| 381 | API_AVAILABLE(macos(13.0), ios(16.0), tvos(16.0), watchos(9.0)) |
| 382 | XPC_EXPORT XPC_SWIFT_NOEXPORT |
| 383 | void |
| 384 | xpc_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 | */ |
| 418 | API_AVAILABLE(macos(14.4)) |
| 419 | API_UNAVAILABLE(ios, tvos, watchos) |
| 420 | XPC_EXPORT XPC_NONNULL_ALL XPC_WARN_RESULT |
| 421 | int |
| 422 | xpc_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 | */ |
| 446 | API_AVAILABLE(macos(26.0), ios(26.0), tvos(26.0), watchos(26.0)) |
| 447 | |
| 448 | XPC_EXPORT XPC_SWIFT_NOEXPORT XPC_NONNULL_ALL |
| 449 | void |
| 450 | xpc_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) |
| 454 | XPC_EXPORT |
| 455 | XPC_TYPE(_xpc_type_session); |
| 456 | |
| 457 | __END_DECLS |
| 458 | XPC_ASSUME_NONNULL_END |
| 459 | |
| 460 | #endif // __XPC_SESSION_H__ |