2024-12-13 03:55:54 +01:00

1005 lines
41 KiB
C
Vendored
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef __XPC_CONNECTION_H__
#define __XPC_CONNECTION_H__
#ifndef __XPC_INDIRECT__
#error "Please #include <xpc/xpc.h> instead of this file directly."
// For HeaderDoc.
#include <xpc/base.h>
#endif // __XPC_INDIRECT__
#ifndef __BLOCKS__
#error "XPC connections require Blocks support."
#endif // __BLOCKS__
XPC_ASSUME_NONNULL_BEGIN
__BEGIN_DECLS
/*!
* @constant XPC_ERROR_CONNECTION_INTERRUPTED
* Will be delivered to the connection's event handler if the remote service
* exited. The connection is still live even in this case, and resending a
* message will cause the service to be launched on-demand. This error serves
* as a client's indication that it should resynchronize any state that it had
* given the service.
*
* Any messages in the queue to be sent will be unwound and canceled when this
* error occurs. In the case where a message waiting to be sent has a reply
* handler, that handler will be invoked with this error. In the context of the
* reply handler, this error indicates that a reply to the message will never
* arrive.
*
* Messages that do not have reply handlers associated with them will be
* silently disposed of. This error will only be given to peer connections.
*/
#define XPC_ERROR_CONNECTION_INTERRUPTED \
XPC_GLOBAL_OBJECT(_xpc_error_connection_interrupted)
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0)
XPC_EXPORT
const struct _xpc_dictionary_s _xpc_error_connection_interrupted;
/*!
* @constant XPC_ERROR_CONNECTION_INVALID
* Will be delivered to the connection's event handler if the named service
* provided to xpc_connection_create() could not be found in the XPC service
* namespace. The connection is useless and should be disposed of.
*
* Any messages in the queue to be sent will be unwound and canceled when this
* error occurs, similarly to the behavior when XPC_ERROR_CONNECTION_INTERRUPTED
* occurs. The only difference is that the XPC_ERROR_CONNECTION_INVALID will be
* given to outstanding reply handlers and the connection's event handler.
*
* This error may be given to any type of connection.
*/
#define XPC_ERROR_CONNECTION_INVALID \
XPC_GLOBAL_OBJECT(_xpc_error_connection_invalid)
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0)
XPC_EXPORT
const struct _xpc_dictionary_s _xpc_error_connection_invalid;
/*!
* @constant XPC_ERROR_TERMINATION_IMMINENT
* On macOS, this error will be delivered to a peer connection's event handler
* when the XPC runtime has determined that the program should exit and that
* all outstanding transactions must be wound down, and no new transactions can
* be opened.
*
* After this error has been delivered to the event handler, no more messages
* will be received by the connection. The runtime will still attempt to deliver
* outgoing messages, but this error should be treated as an indication that
* the program will exit very soon, and any outstanding business over the
* connection should be wrapped up as quickly as possible and the connection
* canceled shortly thereafter.
*
* This error will only be delivered to peer connections received through a
* listener or the xpc_main() event handler.
*/
#define XPC_ERROR_TERMINATION_IMMINENT \
XPC_GLOBAL_OBJECT(_xpc_error_termination_imminent)
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0)
XPC_EXPORT
const struct _xpc_dictionary_s _xpc_error_termination_imminent;
/*!
* @constant XPC_ERROR_PEER_CODE_SIGNING_REQUIREMENT
* On macOS, this error will be delivered to a peer connection's event handler
* when the XPC runtime has detected that a peer connection does not
* satisfy the code signing requirement specified for the connection.
*
* See {@link xpc_connection_set_peer_code_signing_requirement}
*/
#define XPC_ERROR_PEER_CODE_SIGNING_REQUIREMENT \
XPC_GLOBAL_OBJECT(_xpc_error_peer_code_signing_requirement)
__API_AVAILABLE(macos(12.0), macCatalyst(15.0))
XPC_EXPORT
const struct _xpc_dictionary_s _xpc_error_peer_code_signing_requirement;
/*!
* @constant XPC_CONNECTION_MACH_SERVICE_LISTENER
* Passed to xpc_connection_create_mach_service(). This flag indicates that the
* caller is the listener for the named service. This flag may only be passed
* for services which are advertised in the process' launchd.plist(5). You may
* not use this flag to dynamically add services to the Mach bootstrap
* namespace.
*/
#define XPC_CONNECTION_MACH_SERVICE_LISTENER (1 << 0)
/*!
* @constant XPC_CONNECTION_MACH_SERVICE_PRIVILEGED
* Passed to xpc_connection_create_mach_service(). This flag indicates that the
* job advertising the service name in its launchd.plist(5) should be in the
* privileged Mach bootstrap. This is typically accomplished by placing your
* launchd.plist(5) in /Library/LaunchDaemons. If specified alongside the
* XPC_CONNECTION_MACH_SERVICE_LISTENER flag, this flag is a no-op.
*/
#define XPC_CONNECTION_MACH_SERVICE_PRIVILEGED (1 << 1)
/*!
* @typedef xpc_finalizer_f
* A function that is invoked when a connection is being torn down and its
* context needs to be freed. The sole argument is the value that was given to
* {@link xpc_connection_set_context} or NULL if no context has been set. It is
* not safe to reference the connection from within this function.
*
* @param value
* The context object that is to be disposed of.
*/
typedef void (*xpc_finalizer_t)(void * _Nullable value);
/*!
* @function xpc_connection_create
* Creates a new connection object.
*
* @param name
* If non-NULL, the name of the service with which to connect. The returned
* connection will be a peer.
*
* If NULL, an anonymous listener connection will be created. You can embed the
* ability to create new peer connections in an endpoint, which can be inserted
* into a message and sent to another process .
*
* @param targetq
* The GCD queue to which the event handler block will be submitted. This
* parameter may be NULL, in which case the connection's target queue will be
* libdispatch's default target queue, defined as DISPATCH_TARGET_QUEUE_DEFAULT.
* The target queue may be changed later with a call to
* xpc_connection_set_target_queue().
*
* @result
* A new connection object. The caller is responsible for disposing of the
* returned object with {@link xpc_release} when it is no longer needed.
*
* @discussion
* This method will succeed even if the named service does not exist. This is
* because the XPC namespace is not queried for the service name until the
* connection has been activated. See {@link xpc_connection_activate()}.
*
* XPC connections, like dispatch sources, are returned in an inactive state, so
* you must call {@link xpc_connection_activate()} in order to begin receiving
* events from the connection. Also like dispatch sources, connections must be
* activated and not suspended in order to be safely released. It is
* a programming error to release an inactive or suspended connection.
*/
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0)
XPC_EXPORT XPC_MALLOC XPC_RETURNS_RETAINED XPC_WARN_RESULT
xpc_connection_t
xpc_connection_create(const char * _Nullable name,
dispatch_queue_t _Nullable targetq);
/*!
* @function xpc_connection_create_mach_service
* Creates a new connection object representing a Mach service.
*
* @param name
* The name of the remote service with which to connect. The service name must
* exist in a Mach bootstrap that is accessible to the process and be advertised
* in a launchd.plist.
*
* @param targetq
* The GCD queue to which the event handler block will be submitted. This
* parameter may be NULL, in which case the connection's target queue will be
* libdispatch's default target queue, defined as DISPATCH_TARGET_QUEUE_DEFAULT.
* The target queue may be changed later with a call to
* xpc_connection_set_target_queue().
*
* @param flags
* Additional attributes with which to create the connection.
*
* @result
* A new connection object.
*
* @discussion
* If the XPC_CONNECTION_MACH_SERVICE_LISTENER flag is given to this method,
* then the connection returned will be a listener connection. Otherwise, a peer
* connection will be returned. See the documentation for
* {@link xpc_connection_set_event_handler()} for the semantics of listener
* connections versus peer connections.
*
* This method will succeed even if the named service does not exist. This is
* because the Mach namespace is not queried for the service name until the
* connection has been activated. See {@link xpc_connection_activate()}.
*/
API_AVAILABLE(macos(10.7), macCatalyst(5.0))
API_UNAVAILABLE(ios)
XPC_EXPORT XPC_MALLOC XPC_RETURNS_RETAINED XPC_WARN_RESULT XPC_NONNULL1
xpc_connection_t
xpc_connection_create_mach_service(const char *name,
dispatch_queue_t _Nullable targetq, uint64_t flags);
/*!
* @function xpc_connection_create_from_endpoint
* Creates a new connection from the given endpoint.
*
* @param endpoint
* The endpoint from which to create the new connection.
*
* @result
* A new peer connection to the listener represented by the given endpoint.
*
* The same responsibilities of setting an event handler and activating the
* connection after calling xpc_connection_create() apply to the connection
* returned by this API. Since the connection yielded by this API is not
* associated with a name (and therefore is not rediscoverable), this connection
* will receive XPC_ERROR_CONNECTION_INVALID if the listening side crashes,
* exits or cancels the listener connection.
*/
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0)
XPC_EXPORT XPC_MALLOC XPC_RETURNS_RETAINED XPC_WARN_RESULT XPC_NONNULL_ALL
xpc_connection_t
xpc_connection_create_from_endpoint(xpc_endpoint_t endpoint);
/*!
* @function xpc_connection_set_target_queue
* Sets the target queue of the given connection.
*
* @param connection
* The connection object which is to be manipulated.
*
* @param targetq
* The GCD queue to which the event handler block will be submitted. This
* parameter may be NULL, in which case the connection's target queue will be
* libdispatch's default target queue, defined as DISPATCH_TARGET_QUEUE_DEFAULT.
*
* @discussion
* Setting the target queue is asynchronous and non-preemptive and therefore
* this method will not interrupt the execution of an already-running event
* handler block. Setting the target queue may be likened to issuing a barrier
* to the connection which does the actual work of changing the target queue.
*
* The XPC runtime guarantees this non-preemptiveness even for concurrent target
* queues. If the target queue is a concurrent queue, then XPC still guarantees
* that there will never be more than one invocation of the connection's event
* handler block executing concurrently. If you wish to process events
* concurrently, you can dispatch_async(3) to a concurrent queue from within
* the event handler.
*
* IMPORTANT: When called from within the event handler block,
* dispatch_get_current_queue(3) is NOT guaranteed to return a pointer to the
* queue set with this method.
*
* Despite this seeming inconsistency, the XPC runtime guarantees that, when the
* target queue is a serial queue, the event handler block will execute
* synchronously with respect to other blocks submitted to that same queue. When
* the target queue is a concurrent queue, the event handler block may run
* concurrently with other blocks submitted to that queue, but it will never run
* concurrently with other invocations of itself for the same connection, as
* discussed previously.
*/
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0)
XPC_EXPORT XPC_NONNULL1
void
xpc_connection_set_target_queue(xpc_connection_t connection,
dispatch_queue_t _Nullable targetq);
/*!
* @function xpc_connection_set_event_handler
* Sets the event handler block for the connection.
*
* @param connection
* The connection object which is to be manipulated.
*
* @param handler
* The event handler block.
*
* @discussion
* Setting the event handler is asynchronous and non-preemptive, and therefore
* this method will not interrupt the execution of an already-running event
* handler block. If the event handler is executing at the time of this call, it
* will finish, and then the connection's event handler will be changed before
* the next invocation of the event handler. The XPC runtime guarantees this
* non-preemptiveness even for concurrent target queues.
*
* Connection event handlers are non-reentrant, so it is safe to call
* xpc_connection_set_event_handler() from within the event handler block.
*
* The event handler's execution should be treated as a barrier to all
* connection activity. When it is executing, the connection will not attempt to
* send or receive messages, including reply messages. Thus, it is not safe to
* call xpc_connection_send_message_with_reply_sync() on the connection from
* within the event handler.
*
* You do not hold a reference on the object received as the event handler's
* only argument. Regardless of the type of object received, it is safe to call
* xpc_retain() on the object to obtain a reference to it.
*
* A connection may receive different events depending upon whether it is a
* listener or not. Any connection may receive an error in its event handler.
* But while normal connections may receive messages in addition to errors,
* listener connections will receive connections and and not messages.
*
* Connections received by listeners are equivalent to those returned by
* xpc_connection_create() with a non-NULL name argument and a NULL targetq
* argument with the exception that you do not hold a reference on them.
* You must set an event handler and activate the connection. If you do not wish
* to accept the connection, you may simply call xpc_connection_cancel() on it
* and return. The runtime will dispose of it for you.
*
* If there is an error in the connection, this handler will be invoked with the
* error dictionary as its argument. This dictionary will be one of the well-
* known XPC_ERROR_* dictionaries.
*
* Regardless of the type of event, ownership of the event object is NOT
* implicitly transferred. Thus, the object will be released and deallocated at
* some point in the future after the event handler returns. If you wish the
* event's lifetime to persist, you must retain it with xpc_retain().
*
* Connections received through the event handler will be released and
* deallocated after the connection has gone invalid and delivered that event to
* its event handler.
*/
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0)
XPC_EXPORT XPC_NONNULL_ALL
void
xpc_connection_set_event_handler(xpc_connection_t connection,
xpc_handler_t handler);
/*!
* @function xpc_connection_activate
* Activates the connection. Connections start in an inactive state, so you must
* call xpc_connection_activate() on a connection before it will send or receive
* any messages.
*
* @param connection
* The connection object which is to be manipulated.
*
* @discussion
* Calling xpc_connection_activate() on an active connection has no effect.
* Releasing the last reference on an inactive connection that was created with
* an xpc_connection_create*() call is undefined.
*
* For backward compatibility reasons, xpc_connection_resume() on an inactive
* and not otherwise suspended xpc connection has the same effect as calling
* xpc_connection_activate(). For new code, using xpc_connection_activate()
* is preferred.
*/
__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0)
__TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0)
XPC_EXPORT XPC_NONNULL_ALL
void
xpc_connection_activate(xpc_connection_t connection);
/*!
* @function xpc_connection_suspend
* Suspends the connection so that the event handler block will not fire and
* that the connection will not attempt to send any messages it has in its
* queue. All calls to xpc_connection_suspend() must be balanced with calls to
* xpc_connection_resume() before releasing the last reference to the
* connection.
*
* @param connection
* The connection object which is to be manipulated.
*
* @discussion
* Suspension is asynchronous and non-preemptive, and therefore this method will
* not interrupt the execution of an already-running event handler block. If
* the event handler is executing at the time of this call, it will finish, and
* then the connection will be suspended before the next scheduled invocation
* of the event handler. The XPC runtime guarantees this non-preemptiveness even
* for concurrent target queues.
*
* Connection event handlers are non-reentrant, so it is safe to call
* xpc_connection_suspend() from within the event handler block.
*/
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0)
XPC_EXPORT XPC_NONNULL_ALL
void
xpc_connection_suspend(xpc_connection_t connection);
/*!
* @function xpc_connection_resume
* Resumes the connection.
*
* @param connection
* The connection object which is to be manipulated.
*
* @discussion
* In order for a connection to become live, every call to
* xpc_connection_suspend() must be balanced with a call to
* xpc_connection_resume().
*
* For backward compatibility reasons, xpc_connection_resume() on an inactive
* and not otherwise suspended xpc connection has the same effect as calling
* xpc_connection_activate(). For new code, using xpc_connection_activate()
* is preferred.
*
* Calling xpc_connection_resume() more times than xpc_connection_suspend()
* has been called is otherwise considered an error.
*/
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0)
XPC_EXPORT XPC_NONNULL_ALL
void
xpc_connection_resume(xpc_connection_t connection);
/*!
* @function xpc_connection_send_message
* Sends a message over the connection to the destination service.
*
* @param connection
* The connection over which the message shall be sent.
*
* @param message
* The message to send. This must be a dictionary object. This dictionary is
* logically copied by the connection, so it is safe to modify the dictionary
* after this call.
*
* @discussion
* Messages are delivered in FIFO order. This API is safe to call from multiple
* GCD queues. There is no indication that a message was delivered successfully.
* This is because even once the message has been successfully enqueued on the
* remote end, there are no guarantees about when the runtime will dequeue the
* message and invoke the other connection's event handler block.
*
* If this API is used to send a message that is in reply to another message,
* there is no guarantee of ordering between the invocations of the connection's
* event handler and the reply handler for that message, even if they are
* targeted to the same queue.
*
* After extensive study, we have found that clients who are interested in
* the state of the message on the server end are typically holding open
* transactions related to that message. And the only reliable way to track the
* lifetime of that transaction is at the protocol layer. So the server should
* send a reply message, which upon receiving, will cause the client to close
* its transaction.
*/
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0)
XPC_EXPORT XPC_NONNULL_ALL
void
xpc_connection_send_message(xpc_connection_t connection, xpc_object_t message);
/*!
* @function xpc_connection_send_barrier
* Issues a barrier against the connection's message-send activity.
*
* @param connection
* The connection against which the barrier is to be issued.
*
* @param barrier
* The barrier block to issue. This barrier prevents concurrent message-send
* activity on the connection. No messages will be sent while the barrier block
* is executing.
*
* @discussion
* XPC guarantees that, even if the connection's target queue is a concurrent
* queue, there are no other messages being sent concurrently while the barrier
* block is executing. XPC does not guarantee that the receipt of messages
* (either through the connection's event handler or through reply handlers)
* will be suspended while the barrier is executing.
*
* A barrier is issued relative to the message-send queue. Thus, if you call
* xpc_connection_send_message() five times and then call
* xpc_connection_send_barrier(), the barrier will be invoked after the fifth
* message has been sent and its memory disposed of. You may safely cancel a
* connection from within a barrier block.
*
* If a barrier is issued after sending a message which expects a reply, the
* behavior is the same as described above. The receipt of a reply message will
* not influence when the barrier runs.
*
* A barrier block can be useful for throttling resource consumption on the
* connected side of a connection. For example, if your connection sends many
* large messages, you can use a barrier to limit the number of messages that
* are inflight at any given time. This can be particularly useful for messages
* that contain kernel resources (like file descriptors) which have a system-
* wide limit.
*
* If a barrier is issued on a canceled connection, it will be invoked
* immediately. If a connection has been canceled and still has outstanding
* barriers, those barriers will be invoked as part of the connection's
* unwinding process.
*
* It is important to note that a barrier block's execution order is not
* guaranteed with respect to other blocks that have been scheduled on the
* target queue of the connection. Or said differently,
* xpc_connection_send_barrier(3) is not equivalent to dispatch_async(3).
*/
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0)
XPC_EXPORT XPC_NONNULL_ALL
void
xpc_connection_send_barrier(xpc_connection_t connection,
dispatch_block_t barrier);
/*!
* @function xpc_connection_send_message_with_reply
* Sends a message over the connection to the destination service and associates
* a handler to be invoked when the remote service sends a reply message.
*
* @param connection
* The connection over which the message shall be sent.
*
* @param message
* The message to send. This must be a dictionary object.
*
* @param replyq
* The GCD queue to which the reply handler will be submitted. This may be a
* concurrent queue.
*
* @param handler
* The handler block to invoke when a reply to the message is received from
* the connection. If the remote service exits prematurely before the reply was
* received, the XPC_ERROR_CONNECTION_INTERRUPTED error will be returned.
* If the connection went invalid before the message could be sent, the
* XPC_ERROR_CONNECTION_INVALID error will be returned.
*
* @discussion
* If the given GCD queue is a concurrent queue, XPC cannot guarantee that there
* will not be multiple reply handlers being invoked concurrently. XPC does not
* guarantee any ordering for the invocation of reply handlers. So if multiple
* messages are waiting for replies and the connection goes invalid, there is no
* guarantee that the reply handlers will be invoked in FIFO order. Similarly,
* XPC does not guarantee that reply handlers will not run concurrently with
* the connection's event handler in the case that the reply queue and the
* connection's target queue are the same concurrent queue.
*/
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0)
XPC_EXPORT XPC_NONNULL1 XPC_NONNULL2 XPC_NONNULL4
void
xpc_connection_send_message_with_reply(xpc_connection_t connection,
xpc_object_t message, dispatch_queue_t _Nullable replyq,
xpc_handler_t handler);
/*!
* @function xpc_connection_send_message_with_reply_sync
* Sends a message over the connection and blocks the caller until a reply is
* received.
*
* @param connection
* The connection over which the message shall be sent.
*
* @param message
* The message to send. This must be a dictionary object.
*
* @result
* The message that the remote service sent in reply to the original message.
* If the remote service exits prematurely before the reply was received, the
* XPC_ERROR_CONNECTION_INTERRUPTED error will be returned. If the connection
* went invalid before the message could be sent, the
* XPC_ERROR_CONNECTION_INVALID error will be returned.
*
* You are responsible for releasing the returned object.
*
* @discussion
* This API supports priority inversion avoidance, and should be used instead of
* combining xpc_connection_send_message_with_reply() with a semaphore.
*
* Invoking this API from a queue that is a part of the target queue hierarchy
* results in deadlocks under certain conditions.
*
* Be judicious about your use of this API. It can block indefinitely, so if you
* are using it to implement an API that can be called from the main thread, you
* may wish to consider allowing the API to take a queue and callback block so
* that results may be delivered asynchronously if possible.
*/
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0)
XPC_EXPORT XPC_NONNULL_ALL XPC_WARN_RESULT XPC_RETURNS_RETAINED
xpc_object_t
xpc_connection_send_message_with_reply_sync(xpc_connection_t connection,
xpc_object_t message);
/*!
* @function xpc_connection_cancel
* Cancels the connection and ensures that its event handler will not fire
* again. After this call, any messages that have not yet been sent will be
* discarded, and the connection will be unwound. If there are messages that are
* awaiting replies, they will have their reply handlers invoked with the
* XPC_ERROR_CONNECTION_INVALID error.
*
* @param connection
* The connection object which is to be manipulated.
*
* @discussion
* Cancellation is asynchronous and non-preemptive and therefore this method
* will not interrupt the execution of an already-running event handler block.
* If the event handler is executing at the time of this call, it will finish,
* and then the connection will be canceled, causing a final invocation of the
* event handler to be scheduled with the XPC_ERROR_CONNECTION_INVALID error.
* After that invocation, there will be no further invocations of the event
* handler.
*
* The XPC runtime guarantees this non-preemptiveness even for concurrent target
* queues.
*/
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0)
XPC_EXPORT XPC_NONNULL_ALL
void
xpc_connection_cancel(xpc_connection_t connection);
/*!
* @function xpc_connection_get_name
* Returns the name of the service with which the connections was created.
*
* @param connection
* The connection object which is to be examined.
*
* @result
* The name of the remote service. If you obtained the connection through an
* invocation of another connection's event handler, NULL is returned.
*/
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0)
XPC_EXPORT XPC_NONNULL_ALL XPC_WARN_RESULT
const char * _Nullable
xpc_connection_get_name(xpc_connection_t connection);
/*!
* @function xpc_connection_get_euid
* Returns the EUID of the remote peer.
*
* @param connection
* The connection object which is to be examined.
*
* @result
* The EUID of the remote peer at the time the connection was made.
*/
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0)
XPC_EXPORT XPC_NONNULL_ALL XPC_WARN_RESULT
uid_t
xpc_connection_get_euid(xpc_connection_t connection);
/*!
* @function xpc_connection_get_egid
* Returns the EGID of the remote peer.
*
* @param connection
* The connection object which is to be examined.
*
* @result
* The EGID of the remote peer at the time the connection was made.
*/
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0)
XPC_EXPORT XPC_NONNULL_ALL XPC_WARN_RESULT
gid_t
xpc_connection_get_egid(xpc_connection_t connection);
/*!
* @function xpc_connection_get_pid
* Returns the PID of the remote peer.
*
* @param connection
* The connection object which is to be examined.
*
* @result
* The PID of the remote peer.
*
* @discussion
* A given PID is not guaranteed to be unique across an entire boot cycle.
* Great care should be taken when dealing with this information, as it can go
* stale after the connection is established. OS X recycles PIDs, and therefore
* another process could spawn and claim the PID before a message is actually
* received from the connection.
*
* XPC will deliver an error to your event handler if the remote process goes
* away, but there are no guarantees as to the timing of this notification's
* delivery either at the kernel layer or at the XPC layer.
*/
API_AVAILABLE(macos(10.7))
API_UNAVAILABLE(ios)
XPC_EXPORT XPC_NONNULL_ALL XPC_WARN_RESULT
pid_t
xpc_connection_get_pid(xpc_connection_t connection);
/*!
* @function xpc_connection_get_asid
* Returns the audit session identifier of the remote peer.
*
* @param connection
* The connection object which is to be examined.
*
* @result
* The audit session ID of the remote peer at the time the connection was made.
*/
API_AVAILABLE(macos(10.7))
API_UNAVAILABLE(ios)
XPC_EXPORT XPC_NONNULL_ALL XPC_WARN_RESULT
au_asid_t
xpc_connection_get_asid(xpc_connection_t connection);
/*!
* @function xpc_connection_set_context
* Sets context on an connection.
*
* @param connection
* The connection which is to be manipulated.
*
* @param context
* The context to associate with the connection.
*
* @discussion
* If you must manage the memory of the context object, you must set a finalizer
* to dispose of it. If this method is called on a connection which already has
* context associated with it, the finalizer will NOT be invoked. The finalizer
* is only invoked when the connection is being deallocated.
*
* It is recommended that, instead of changing the actual context pointer
* associated with the object, you instead change the state of the context
* object itself.
*/
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0)
XPC_EXPORT XPC_NONNULL1
void
xpc_connection_set_context(xpc_connection_t connection,
void * _Nullable context);
/*!
* @function xpc_connection_get_context
* Returns the context associated with the connection.
*
* @param connection
* The connection which is to be examined.
*
* @result
* The context associated with the connection. NULL if there has been no context
* associated with the object.
*/
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0)
XPC_EXPORT XPC_NONNULL_ALL XPC_WARN_RESULT
void * _Nullable
xpc_connection_get_context(xpc_connection_t connection);
/*!
* @function xpc_connection_set_finalizer_f
* Sets the finalizer for the given connection.
*
* @param connection
* The connection on which to set the finalizer.
*
* @param finalizer
* The function that will be invoked when the connection's retain count has
* dropped to zero and is being torn down.
*
* @discussion
* This method disposes of the context value associated with a connection, as
* set by {@link xpc_connection_set_context}.
*
* For many uses of context objects, this API allows for a convenient shorthand
* for freeing them. For example, for a context object allocated with malloc(3):
*
* xpc_connection_set_finalizer_f(object, free);
*/
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0)
XPC_EXPORT XPC_NONNULL1
void
xpc_connection_set_finalizer_f(xpc_connection_t connection,
xpc_finalizer_t _Nullable finalizer);
/*!
* @function xpc_connection_set_peer_code_signing_requirement
* Requires that the connection peer satisfies a code signing requirement.
*
* @param connection
* The connection object which is to be modified.
*
* @param requirement
* The code signing requirement to be satisfied by the peer
* It is safe to deallocate the requirement string after calling `xpc_connection_set_peer_code_signing_requirement`
*
* @result
* 0 on success, non-zero on error
*
* @discussion
* This function will return an error promptly if the code signing requirement string is invalid.
*
* It is a programming error to call `xpc_connection_set_peer_code_signing_requirement` more than once per connection.
*
* All messages received on this connection will be checked to ensure they come from a peer who satisfies
* the code signing requirement. For a listener connection, requests that do not satisfy the requirement
* are dropped. When a reply is expected on the connection and the peer does not satisfy the requirement
* `XPC_ERROR_PEER_CODE_SIGNING_REQUIREMENT` will be delivered instead of the reply.
*
* This API is not supported on embedded platforms and will return ENOTSUP.
*
* @see https://developer.apple.com/documentation/technotes/tn3127-inside-code-signing-requirements
*/
__API_AVAILABLE(macos(12.0), macCatalyst(15.0))
API_UNAVAILABLE(ios, tvos, watchos)
XPC_EXPORT XPC_NONNULL_ALL XPC_WARN_RESULT
int
xpc_connection_set_peer_code_signing_requirement(xpc_connection_t connection, const char *requirement);
/*!
* @function xpc_connection_set_peer_entitlement_exists_requirement
* Requires that the connection peer has the specified entitlement
*
* @param connection
* The connection object which is to be modified
*
* @param entitlement
* The entitlement the peer must have
* It is safe to deallocate the entitlement string after calling `xpc_connection_set_peer_entitlement_exists_requirement`
*
* @result
* 0 on success, non-zero on error
*
* @discussion
* This function will return an error promptly if the entitlement requirement is invalid.
*
* It is a programming error to call multiple of the `xpc_connection_set_peer_*_requirement` family of functions on the same
* connection. If more complex combinations of requirements are required, use
* `xpc_connection_set_peer_lightweight_code_requirement`.
*
* All messages received on this connection will be checked to ensure that they come from a peer who satisfies the
* requirement. For a listener connection, requests that do not satisfy the requirement are dropped. When a reply
* is expected on the connection and the peer does not satisfy the requirement `XPC_ERROR_PEER_CODE_SIGNING_REQUIREMENT`
* will be delivered instead of the reply.
*/
API_AVAILABLE(macos(14.4), ios(17.4))
API_UNAVAILABLE(tvos, watchos)
XPC_EXPORT XPC_NONNULL_ALL XPC_WARN_RESULT
int
xpc_connection_set_peer_entitlement_exists_requirement(xpc_connection_t connection, const char *entitlement);
/*!
* @function xpc_connection_set_peer_entitlement_matches_value_requirement
* Requires that the connection peer has the specified entitlement with the matching value
*
* @param connection
* The connection object which is to be modified
*
* @param entitlement
* The entitlement the peer must have
* It is safe to deallocate the entitlement string after calling `xpc_connection_set_peer_entitlement_matches_value_requirement`
*
* @param value
* The value that the entitlement must match
* It is safe to deallocate the value object after calling
* `xpc_connection_set_peer_entitlement_matches_value_requirement`.
* Valid xpc types for this object are `XPC_TYPE_BOOL`, `XPC_TYPE_STRING` and `XPC_TYPE_INT64`.
*
* @result
* 0 on success, non-zero on error
*
* @discussion
* This function will return an error promptly if the entitlement requirement is invalid.
*
* It is a programming error to call multiple of the `xpc_connection_set_peer_*_requirement` family of functions on the same
* connection. If more complex combinations of requirements are required, use
* `xpc_connection_set_peer_lightweight_code_requirement`.
*
* All messages received on this connection will be checked to ensure that they come from a peer who satisfies the
* requirement. For a listener connection, requests that do not satisfy the requirement are dropped. When a reply
* is expected on the connection and the peer does not satisfy the requirement `XPC_ERROR_PEER_CODE_SIGNING_REQUIREMENT`
* will be delivered instead of the reply.
*/
API_AVAILABLE(macos(14.4), ios(17.4))
API_UNAVAILABLE(tvos, watchos)
XPC_EXPORT XPC_NONNULL_ALL XPC_WARN_RESULT
int
xpc_connection_set_peer_entitlement_matches_value_requirement(xpc_connection_t connection, const char *entitlement, xpc_object_t value);
/*!
* @function xpc_connection_set_peer_team_identity_requirement
* Requires that the connection peer has the specified identity and is signed with the same team identifier
* as the current process
*
* @param connection
* The connection object which is to be modified
*
* @param signing_identifier
* The optional signing identifier the peer must have
* It is safe to deallocate the signing identifier string after calling `xpc_connection_set_peer_identity_requirement`
*
* @result
* 0 on success, non-zero on error
*
* @discussion
* This function will return an error promptly if the identity requirement is invalid.
*
* The peer process must be signed as either a Testflight app or an App store app,
* or be signed by an apple issued development certificate, an enterprise distributed
* certificate (embedded only), or a Developer ID certificate (macOS only)
*
* It is a programming error to call multiple of the `xpc_connection_set_peer_*_requirement` family of functions on the same
* connection. If more complex combinations of requirements are required, use
* `xpc_connection_set_peer_lightweight_code_requirement`.
*
* All messages received on this connection will be checked to ensure that they come from a peer who satisfies the
* requirement. For a listener connection, requests that do not satisfy the requirement are dropped. When a reply
* is expected on the connection and the peer does not satisfy the requirement `XPC_ERROR_PEER_CODE_SIGNING_REQUIREMENT`
* will be delivered instead of the reply.
*/
API_AVAILABLE(macos(14.4), ios(17.4))
API_UNAVAILABLE(tvos, watchos)
XPC_EXPORT XPC_NONNULL1 XPC_WARN_RESULT
int
xpc_connection_set_peer_team_identity_requirement(xpc_connection_t connection, const char * _Nullable signing_identifier);
/*!
* @function xpc_connection_set_peer_platform_identity_requirement
* Requires that the connection peer has the specified identity and is signed by Apple
*
* @param connection
* The connection object which is to be modified
*
* @param signing_identifier
* The optional signing identifier the peer must have. If not specified, this function ensures that the peer is signed by Apple
* It is safe to deallocate the signing identifier string after calling `xpc_connection_set_peer_identity_requirement`
*
* @result
* 0 on success, non-zero on error
*
* @discussion
* This function will return an error promptly if the identity requirement is invalid.
*
* The peer process must be signed by Apple. Use `xpc_connection_set_peer_identity_requirement` if the peer
* is not part of the OS.
*
* It is a programming error to call multiple of the `xpc_connection_set_peer_*_requirement` family of functions on the same
* connection. If more complex combinations of requirements are required, use
* `xpc_connection_set_peer_lightweight_code_requirement`.
*
* All messages received on this connection will be checked to ensure that they come from a peer who satisfies the
* requirement. For a listener connection, requests that do not satisfy the requirement are dropped. When a reply
* is expected on the connection and the peer does not satisfy the requirement `XPC_ERROR_PEER_CODE_SIGNING_REQUIREMENT`
* will be delivered instead of the reply.
*/
API_AVAILABLE(macos(14.4), ios(17.4))
API_UNAVAILABLE(tvos, watchos)
XPC_EXPORT XPC_NONNULL1 XPC_WARN_RESULT
int
xpc_connection_set_peer_platform_identity_requirement(xpc_connection_t connection, const char * _Nullable signing_identifier);
/*!
* @function xpc_connection_set_peer_lightweight_code_requirement
* Requires that the connection peer has the specified lightweight code requirement
*
* @param connection
* The connection object which is to be modified
*
* @param lwcr
* The lightweight code requirement the peer must have
* It is safe to deallocate the lightweight code requirement object after calling `xpc_connection_set_peer_lightweight_code_requirement`
*
* @result
* 0 on success, non-zero on error
*
* @discussion
* This function will return an error promptly if the lightweight code requirement is invalid.
*
* The lightweight code requirement must be an `xpc_dictionary_t` equivalent of an LWCR constraint (see
* https://developer.apple.com/documentation/security/defining_launch_environment_and_library_constraints
* for details on the contents of the dictionary)
*
* The lightweight code requirement in the example below uses the $or operator to require that an
* executables either signed with the Team ID 8XCUU22SN2, or is an operating system executable:
* ```c
* xpc_object_t or_val = xpc_dictionary_create_empty();
* xpc_dictionary_set_string(or_val, "team-identifier", "8XCUU22SN2");
* xpc_dictionary_set_int64(or_val, "validation-category", 1);
*
* xpc_object_t lwcr = xpc_dictionary_create_empty();
* xpc_dictionary_set_value(lwcr, "$or", or_val);
*
* xpc_connection_set_peer_lightweight_code_requirement(connection, lwcr);
* ```
*
* It is a programming error to call multiple of the `xpc_connection_set_peer_*_requirement` family of functions on the same
* connection.
*
* All messages received on this connection will be checked to ensure that they come from a peer who satisfies the
* requirement. For a listener connection, requests that do not satisfy the requirement are dropped. When a reply
* is expected on the connection and the peer does not satisfy the requirement `XPC_ERROR_PEER_CODE_SIGNING_REQUIREMENT`
* will be delivered instead of the reply.
*/
API_AVAILABLE(macos(14.4), ios(17.4))
API_UNAVAILABLE(tvos, watchos)
XPC_EXPORT XPC_NONNULL_ALL XPC_WARN_RESULT
int
xpc_connection_set_peer_lightweight_code_requirement(xpc_connection_t connection, xpc_object_t lwcr);
/*!
* @function xpc_connection_copy_invalidation_reason
* Returns a description of why the connection was invalidated.
*
* @param connection
* The connection object to inspect
*
* @result
* Null if the connection has not been invalidated, otherwise a description for why the connection was invalidated.
*/
API_AVAILABLE(macos(12.0), ios(15.0), tvos(15.0), watchos(8.0))
XPC_EXPORT XPC_NONNULL1 XPC_WARN_RESULT
char * _Nullable
xpc_connection_copy_invalidation_reason(xpc_connection_t connection);
__END_DECLS
XPC_ASSUME_NONNULL_END
#endif // __XPC_CONNECTION_H__