// Copyright 2018 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This file contains type and function definitions relevant to Mojo invitation // APIs. // // Note: This header should be compilable as C. #ifndef MOJO_PUBLIC_C_SYSTEM_INVITATION_H_ #define MOJO_PUBLIC_C_SYSTEM_INVITATION_H_ #include <stdint.h> #include "mojo/public/c/system/macros.h" #include "mojo/public/c/system/platform_handle.h" #include "mojo/public/c/system/system_export.h" #include "mojo/public/c/system/types.h" // Flags included in |MojoProcessErrorDetails| indicating additional status // information. MojoProcessErrorFlags; // No flags. #define MOJO_PROCESS_ERROR_FLAG_NONE … // If set, the process has been disconnected. No further // |MojoProcessErrorHandler| invocations occur for it, and any IPC primitives // (message pipes, data pipes) which were connected to it have been or will // imminently be disconnected. #define MOJO_PROCESS_ERROR_FLAG_DISCONNECTED … // Details regarding why an invited process has had its connection to this // process terminated by the system. See |MojoProcessErrorHandler| and // |MojoSendInvitation()|. struct MOJO_ALIGNAS(8) MojoProcessErrorDetails { … }; MOJO_STATIC_ASSERT(…); // An opaque process handle value which must be provided when sending an // invitation to another process via a platform transport. See // |MojoSendInvitation()|. struct MOJO_ALIGNAS(8) MojoPlatformProcessHandle { … }; MOJO_STATIC_ASSERT(…); // Enumeration indicating the type of transport over which an invitation will be // sent or received. MojoInvitationTransportType; // The channel transport type embodies common platform-specific OS primitives // for FIFO message passing: // - For Windows, this is a named pipe. // - For Fuchsia, it's a channel. // - For all other POSIX systems, it's a Unix domain socket pair. // // See |MojoInvitationTransportHandle| for details. #define MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL … // Similar to CHANNEL transport, but used for an endpoint which requires an // additional step to accept an inbound connection. This corresponds to a // bound listening socket on POSIX, or named pipe server handle on Windows. // // The remote endpoint should establish a working connection to the server side // and wrap the handle to that connection using a CHANNEL transport. #define MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER … // Similar to CHANNEL transport. Normally with a CHANNEL transport, the inviting // client sends a secondary sync channel to the invited client, and the invited // client synchronously waits for this before it can accept the invitation. // // With this transport type, the invited client creates its own sync channel and // sends the remote endpoint to the inviting client to be passed along to the // broker. This allows acceptance of incoming invitations to avoid blocking // operations, making both sides of the channel initialization process fully // asynchronous. // // Not supported in all platform sandbox configurations. #define MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_ASYNC … // A transport endpoint over which an invitation may be sent or received via // |MojoSendInvitation()| or |MojoAcceptInvitation()| respectively. struct MOJO_ALIGNAS(8) MojoInvitationTransportEndpoint { … }; MOJO_STATIC_ASSERT(…); // Flags passed to |MojoCreateInvitation()| via |MojoCreateInvitationOptions|. MojoCreateInvitationFlags; // No flags. Default behavior. #define MOJO_CREATE_INVITATION_FLAG_NONE … // Options passed to |MojoCreateInvitation()|. struct MOJO_ALIGNAS(8) MojoCreateInvitationOptions { … }; MOJO_STATIC_ASSERT(…); // Flags passed to |MojoAttachMessagePipeToInvitation()| via // |MojoAttachMessagePipeToInvitationOptions|. MojoAttachMessagePipeToInvitationFlags; // No flags. Default behavior. #define MOJO_ATTACH_MESSAGE_PIPE_TO_INVITATION_FLAG_NONE … // Options passed to |MojoAttachMessagePipeToInvitation()|. struct MOJO_ALIGNAS(8) MojoAttachMessagePipeToInvitationOptions { … }; MOJO_STATIC_ASSERT(…); // Flags passed to |MojoExtractMessagePipeFromInvitation()| via // |MojoExtractMessagePipeFromInvitationOptions|. MojoExtractMessagePipeFromInvitationFlags; // No flags. Default behavior. #define MOJO_EXTRACT_MESSAGE_PIPE_FROM_INVITATION_FLAG_NONE … // Options passed to |MojoExtractMessagePipeFromInvitation()|. struct MOJO_ALIGNAS(8) MojoExtractMessagePipeFromInvitationOptions { … }; MOJO_STATIC_ASSERT(…); // Flags passed to |MojoSendInvitation()| via |MojoSendInvitationOptions|. MojoSendInvitationFlags; // No flags. Default behavior. #define MOJO_SEND_INVITATION_FLAG_NONE … // Send an isolated invitation to the receiver. Isolated invitations only // establish communication between the sender and the receiver. Accepting an // isolated invitation does not make IPC possible between the sender and any // other members of the receiver's process graph, nor does it make IPC possible // between the receiver and any other members of the sender's process graph. // // Invitations sent with this flag set must be accepted with the corresponding // |MOJO_ACCEPT_INVITATION_FLAG_ISOLATED| flag set, and may only have a single // message pipe attached with a name of exactly four zero-bytes ("\0\0\0\0"). #define MOJO_SEND_INVITATION_FLAG_ISOLATED … // Indicates that the invitation is being sent to a process which should be // considered "untrusted."" This may impose various security constraints on what // can be transferred by Mojo between e.g. a broker process and the remote // process in question. #define MOJO_SEND_INVITATION_FLAG_UNTRUSTED_PROCESS … // Indicates that the invitation is being sent to a process which may be running // at an elevated privilege level compared to the broker. Such processes are // implicitly trusted more than others. #define MOJO_SEND_INVITATION_FLAG_ELEVATED … // Indicates that the invitation is being sent from a non-broker to another // non-broker and that the sender is referring its broker to the recipient. // The recipient must except this and accept the invitation with // MOJO_ACCEPT_INVITATION_FLAG_INHERIT_BROKER. #define MOJO_SEND_INVITATION_FLAG_SHARE_BROKER … // Options passed to |MojoSendInvitation()|. struct MOJO_ALIGNAS(8) MojoSendInvitationOptions { … }; MOJO_STATIC_ASSERT(…); // Flags passed to |MojoAcceptInvitation()| via |MojoAcceptInvitationOptions|. MojoAcceptInvitationFlags; // No flags. Default behavior. #define MOJO_ACCEPT_INVITATION_FLAG_NONE … // Accept an isoalted invitation from the sender. See // |MOJO_SEND_INVITATION_FLAG_ISOLATED| for details. #define MOJO_ACCEPT_INVITATION_FLAG_ISOLATED … // The transport endpoint used to accept this invitation should be leaked, i.e. // never closed until it's implicitly closed on process death. This exists to // support adaptation of legacy code to Mojo IPC so that, e.g., a broken pipe // can be used as a reliable indication of remote process death. // // This flag should generally not be used unless strictly necessary, and it is // unsafe to use in any situation where a process may accept multiple // invitations over the course of its lifetime. #define MOJO_ACCEPT_INVITATION_FLAG_LEAK_TRANSPORT_ENDPOINT … // The process accepting this invitation is running at an elevated privilege // level relative to the broker. In order for IPC to function properly when this // flag is specified, the invitation sender must also specify // MOJO_SEND_INVITATION_FLAG_ELEVATED. #define MOJO_ACCEPT_INVITATION_FLAG_ELEVATED … // This invitation is being accepted by a non-broker who expects the sender to // refer its own broker to the caller. Invitations accepted with this flag must // have been sent with MOJO_SEND_INVITATION_FLAG_SHARE_BROKER. #define MOJO_ACCEPT_INVITATION_FLAG_INHERIT_BROKER … // Options passed to |MojoAcceptInvitation()|. struct MOJO_ALIGNAS(8) MojoAcceptInvitationOptions { … }; MOJO_STATIC_ASSERT(…); // Flags passed to |MojoSetDefaultProcessErrorHandler()| via // |MojoSetDefaultProcessErrorHandlerOptions|. MojoSetDefaultProcessErrorHandlerFlags; // No flags. Default behavior. #define MOJO_SET_DEFAULT_PROCESS_ERROR_HANDLER_FLAG_NONE … // Options passed to |MojoSetDefaultProcessErrorHandler()|. struct MOJO_ALIGNAS(8) MojoSetDefaultProcessErrorHandlerOptions { … }; MOJO_STATIC_ASSERT(…); #ifdef __cplusplus extern "C" { #endif // A callback which may be invoked by the system when a connection to an invited // process is terminated due to a communication error (i.e. the invited process // has sent a message which fails some validation check in the system). See // |MojoSendInvitation()|. // // |context| is the value of |context| given to |MojoSendInvitation()| when // inviting the process for whom this callback is being invoked. MojoProcessErrorHandler; // Similar to above, but registered globally via // |MojoSetDefaultProcessErrorHandler()| and invoked only for communication // errors regarding processes NOT invited by the calling process. MojoDefaultProcessErrorHandler; // Creates a new invitation to be sent to another process. // // An invitation is used to invite another process to join this process's // IPC network. The caller must already be a member of a Mojo network, either // either by itself having been previously invited, or by being the Mojo broker // process initialized via the Mojo Core Embedder API. // // Invitations can have message pipes attached to them, and these message pipes // are used to bootstrap Mojo IPC between the inviter and the invitee. See // |MojoAttachMessagePipeToInvitation()| for attaching message pipes, and // |MojoSendInvitation()| for sending an invitation. // // |options| controls behavior. May be null for default behavior. // |invitation_handle| must be the address of storage for a MojoHandle value // to be output upon success. // // NOTE: If discarding an invitation instead of sending it with // |MojoSendInvitation()|, you must close its handle (i.e. |MojoClose()|) to // avoid leaking associated system resources. // // Returns: // |MOJO_RESULT_OK| if the invitation was created successfully. The new // invitation's handle is stored in |*invitation_handle| before returning. // |MOJO_RESULT_INVALID_ARGUMENT| if |options| was non-null but malformed. // |MOJO_RESULT_RESOURCE_EXHAUSTED| if a handle could not be allocated for the // new invitation. MOJO_SYSTEM_EXPORT MojoResult MojoCreateInvitation(const struct MojoCreateInvitationOptions* options, MojoHandle* invitation_handle); // Attaches a message pipe endpoint to an invitation. // // This creates a new message pipe which will span the boundary between the // calling process and the invitation's eventual target process. One end of the // new pipe is attached to the invitation while the other end is returned to the // caller. Every attached message pipe has an arbitrary |name| value which // identifies it within the invitation. // // Message pipes can be extracted by the recipient by calling // |MojoExtractMessagePipeFromInvitation()|. It is up to applications to // communicate out-of-band or establish a convention for how attached pipes // are named. // // |invitation_handle| is the invitation to which a pipe should be attached. // |name| is an arbitrary name to give this pipe, required to extract the pipe // on the receiving end of the invitation. Note that the name is scoped to // this invitation only, so e.g. multiple invitations may attach pipes with // the name "foo", but any given invitation may only have a single pipe // attached with that name. // |name_num_bytes| is the number of bytes from |name| to use as the name. // |options| controls behavior. May be null for default behavior. // |message_pipe_handle| is the address of storage for a MojoHandle value. // Upon success, the handle of the local endpoint of the new message pipe // will be stored here. // // Returns: // |MOJO_RESULT_OK| if the pipe was created and attached successfully. The // local endpoint of the pipe has its handle stored in // |*message_pipe_handle| before returning. The other endpoint is attached // to the invitation. // |MOJO_RESULT_INVALID_ARGUMENT| if |invitation_handle| was not an invitation // handle, |options| was non-null but malformed, or |message_pipe_handle| // was null. // |MOJO_RESULT_ALREADY_EXISTS| if |name| was already in use for this // invitation. // |MOJO_RESULT_RESOURCE_EXHAUSTED| if a handle could not be allocated for the // new local message pipe endpoint. MOJO_SYSTEM_EXPORT MojoResult MojoAttachMessagePipeToInvitation( MojoHandle invitation_handle, const void* name, uint32_t name_num_bytes, const struct MojoAttachMessagePipeToInvitationOptions* options, MojoHandle* message_pipe_handle); // Extracts a message pipe endpoint from an invitation. // // |invitation_handle| is the invitation from which to extract the endpoint. // |name| is the name of the endpoint within the invitation. This corresponds // to the name that was given to |MojoAttachMessagePipeToInvitation()| when // the endpoint was attached. // |name_num_bytes| is the number of bytes from |name| to use as the name. // |options| controls behavior. May be null for default behavior. // |message_pipe_handle| is the address of storage for a MojoHandle value. // Upon success, the handle of the extracted message pipe endpoint will be // stored here. // // Note that it is possible to extract an endpoint from an invitation even // before the invitation has been sent to a remote process. If this is done and // then the invitation is sent, the receiver will not see this endpoint as it // will no longer be attached. // // Returns: // |MOJO_RESULT_OK| if a new local message pipe endpoint was successfully // created and returned in |*message_pipe_handle|. Note that the // association of this endpoint with an invitation attachment is // necessarily an asynchronous operation, and it is not known at return // whether an attachment named |name| actually exists on the invitation. // As such, the operation may still fail eventually, resuling in a broken // pipe, i.e. the extracted pipe will signal peer closure. // |MOJO_RESULT_INVALID_ARGUMENT| if |invitation_handle| was not an invitation // handle, |options| was non-null but malformed, or |message_pipe_handle| // was null. // |MOJO_RESULT_RESOURCE_EXHAUSTED| if a handle could not be allocated for the // new local message pipe endpoint. // |MOJO_RESULT_NOT_FOUND| if it is known at call time that there is no pipe // named |name| attached to the invitation. This is possible if the // invtation was created within the calling process by // |MojoCreateInvitation()|. MOJO_SYSTEM_EXPORT MojoResult MojoExtractMessagePipeFromInvitation( MojoHandle invitation_handle, const void* name, uint32_t name_num_bytes, const struct MojoExtractMessagePipeFromInvitationOptions* options, MojoHandle* message_pipe_handle); // Sends an invitation on a transport endpoint to bootstrap IPC between the // calling process and another process. // // |invitation_handle| is the handle of the invitation to send. // |process_handle| is an opaque, platform-specific handle to the remote // process. See |MojoPlatformProcessHandle|. This is not necessarily // required to be a valid process handle, but on some platforms (namely // Windows and Mac) it's important if the invitation target will need to // send or receive any kind of platform handles (including shared memory) // over Mojo message pipes. // |transport_endpoint| is one endpoint of a platform transport primitive, the // other endpoint of which should be established within the process // corresponding to |*process_handle|. See |MojoInvitationTransportEndpoint| // for details. // |error_handler| is a function to invoke if the connection to the invitee // encounters any kind of error condition, e.g. a message validation failure // reported by |MojoNotifyBadMessage()|, or permanent disconnection. See // |MojoProcessErrorDetails| for more information. // |error_handler_context| is an arbitrary value to be associated with this // process invitation. This value is passed as the |context| argument to // |error_handler| when invoked regarding this invitee. // |options| controls behavior. May be null for default behavior. // // This assumes ownership of any platform handles in |transport_endpoint| if // and only if returning |MOJO_RESULT_OK|. In that case, |invitation_handle| is // also invalidated. // // NOTE: It's pointless to send an invitation without at least one message pipe // attached, so it is considered an error to attempt to do so. // // Returns: // |MOJO_RESULT_OK| if the invitation was successfully sent over the // transport. |invitation_handle| is implicitly closed. Note that this // does not guarantee that the invitation has been received by the target // yet, or that it ever will be (e.g. the target process may terminate // first or simply fail to accept the invitation). // |MOJO_RESULT_INVALID_ARGUMENT| if |invitation_handle| was not an invitation // handle, |transport_endpoint| was null or malformed, or |options| was // non-null but malformed. // |MOJO_RESULT_ABORTED| if the system failed to issue any necessary // communication via |transport_endpoint|, possibly due to a configuration // issue with the endpoint. The caller may attempt to correct this // situation and call again. // |MOJO_RESULT_FAILED_PRECONDITION| if there were no message pipes attached // to the invitation. The caller may correct this situation and call // again. // |MOJO_RESULT_UNIMPLEMENTED| if the transport endpoint type is not supported // by the system's version of Mojo. MOJO_SYSTEM_EXPORT MojoResult MojoSendInvitation( MojoHandle invitation_handle, const struct MojoPlatformProcessHandle* process_handle, const struct MojoInvitationTransportEndpoint* transport_endpoint, MojoProcessErrorHandler error_handler, uintptr_t error_handler_context, const struct MojoSendInvitationOptions* options); // Accepts an invitation from a transport endpoint to complete IPC bootstrapping // between the calling process and whoever sent the invitation from the other // end of the transport. // // |transport_endpoint| is one endpoint of a platform transport primitive, the // other endpoint of which should be established within a process // who has sent or will send an invitation via that endpoint. See // |MojoInvitationTransportEndpoint| for details. // |options| controls behavior. May be null for default behavior. // |invitation_handle| is the address of storage for a MojoHandle value. Upon // success, the handle of the accepted invitation will be stored here. // // Once an invitation is accepted, message pipes endpoints may be extracted from // it by calling |MojoExtractMessagePipeFromInvitation()|. // // Note that it is necessary to eventually close (i.e. |MojoClose()|) any // accepted invitation handle in order to clean up any associated system // resources. If an accepted invitation is closed while it still has message // pipes attached (i.e. not exracted as above), those pipe endpoints are also // closed. // // Returns: // |MOJO_RESULT_OK| if the invitation was successfully accepted. The handle // to the invitation is stored in |*invitation_handle| before returning. // |MOJO_RESULT_INVALID_ARGUMENT| if |transport_endpoint| was null or // malfored, |options| was non-null but malformed, or |invitation_handle| // was null. // |MOJO_RESULT_ABORTED| if the system failed to receive any communication via // |transport_endpoint|, possibly due to some configuration error. The // caller may attempt to correct this situation and call again. // |MOJO_RESULT_UNIMPLEMENTED| if the transport endpoint type is not supported // by the system's version of Mojo. MOJO_SYSTEM_EXPORT MojoResult MojoAcceptInvitation( const struct MojoInvitationTransportEndpoint* transport_endpoint, const struct MojoAcceptInvitationOptions* options, MojoHandle* invitation_handle); // Registers a process-wide handler to be invoked when an error is raised on a // connection to a peer process. Such errors can be raised if the peer process // sends malformed data to this process. // // Note that this handler is only invoked for connections to processes NOT // explicitly invited by this process. To handle errors concerning processes // invited by this process, see the MojoProcessErrorHandler argument to // |MojoSendInvitation()|. // // The general use case for this API is to be able to log or report instances of // bad IPCs received by a client process which no real ability or authority to // identify the source. // // Returns: // |MOJO_RESULT_OK| if |handler| is successfully registered as the global // default process error handler within the calling process. If |handler| // is null, any registered default process error handler is removed. // |MOJO_RESULT_ALREADY_EXISTS| if |handler| is non-null and there is already // a registered error handler. Callers wishing to replace an existing // handler must first call |MojoSetDefaultProcessErrorHandler()| with null // in order to do so. MOJO_SYSTEM_EXPORT MojoResult MojoSetDefaultProcessErrorHandler( MojoDefaultProcessErrorHandler handler, const struct MojoSetDefaultProcessErrorHandlerOptions* options); #ifdef __cplusplus } // extern "C" #endif #endif // MOJO_PUBLIC_C_SYSTEM_INVITATION_H_