// Copyright 2018 The Chromium Authors. All rights reserved. // 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 #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. typedef uint32_t MojoProcessErrorFlags; // No flags. #define MOJO_PROCESS_ERROR_FLAG_NONE ((MojoProcessErrorFlags)0) // 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 ((MojoProcessErrorFlags)1) // 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 { // The size of this structure, used for versioning. uint32_t struct_size; // The length of the string pointed to by |error_message| below. uint32_t error_message_length; // An error message corresponding to the reason why the connection was // terminated. This is an information message which may be useful to // developers. MOJO_POINTER_FIELD(const char*, error_message); // See |MojoProcessErrorFlags|. MojoProcessErrorFlags flags; }; MOJO_STATIC_ASSERT(sizeof(MojoProcessErrorDetails) == 24, "MojoProcessErrorDetails has wrong size."); // 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 { // The size of this structure, used for versioning. uint32_t struct_size; // The process handle value. For Windows this is a valid process HANDLE value. // For Fuchsia it must be |zx_handle_t| process handle, and for all other // POSIX systems, it's a PID. uint64_t value; }; MOJO_STATIC_ASSERT(sizeof(MojoPlatformProcessHandle) == 16, "MojoPlatformProcesHandle has wrong size."); // Enumeration indicating the type of transport over which an invitation will be // sent or received. typedef uint32_t 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 ((MojoInvitationTransportType)0) // 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 \ ((MojoInvitationTransportType)1) // A transport endpoint over which an invitation may be sent or received via // |MojoSendInvitation()| or |MojoAcceptInvitation()| respectively. struct MOJO_ALIGNAS(8) MojoInvitationTransportEndpoint { // The size of this structure, used for versioning. uint32_t struct_size; // The type of this transport endpoint. See |MojoInvitationTransportType|. MojoInvitationTransportType type; // The number of platform handles in |platform_handles| below. uint32_t num_platform_handles; // Platform handle(s) corresponding to the system object(s) backing this // endpoint. The concrete type of the handle(s) depends on |type|. // // For |MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL| endpoints: // - On Windows, this is a single named pipe HANDLE // - On Fuchsua, this is a single channel Fuchsia handle // - On other POSIX systems, this is a single Unix domain socket file // descriptor. MOJO_POINTER_FIELD(const struct MojoPlatformHandle*, platform_handles); }; MOJO_STATIC_ASSERT(sizeof(MojoInvitationTransportEndpoint) == 24, "MojoInvitationTransportEndpoint has wrong size."); // Flags passed to |MojoCreateInvitation()| via |MojoCreateInvitationOptions|. typedef uint32_t MojoCreateInvitationFlags; // No flags. Default behavior. #define MOJO_CREATE_INVITATION_FLAG_NONE ((MojoCreateInvitationFlags)0) // Options passed to |MojoCreateInvitation()|. struct MOJO_ALIGNAS(8) MojoCreateInvitationOptions { // The size of this structure, used for versioning. uint32_t struct_size; // See |MojoCreateInvitationFlags|. MojoCreateInvitationFlags flags; }; MOJO_STATIC_ASSERT(sizeof(MojoCreateInvitationOptions) == 8, "MojoCreateInvitationOptions has wrong size"); // Flags passed to |MojoAttachMessagePipeToInvitation()| via // |MojoAttachMessagePipeToInvitationOptions|. typedef uint32_t MojoAttachMessagePipeToInvitationFlags; // No flags. Default behavior. #define MOJO_ATTACH_MESSAGE_PIPE_TO_INVITATION_FLAG_NONE \ ((MojoAttachMessagePipeToInvitationFlags)0) // Options passed to |MojoAttachMessagePipeToInvitation()|. struct MOJO_ALIGNAS(8) MojoAttachMessagePipeToInvitationOptions { // The size of this structure, used for versioning. uint32_t struct_size; // See |MojoAttachMessagePipeToInvitationFlags|. MojoAttachMessagePipeToInvitationFlags flags; }; MOJO_STATIC_ASSERT(sizeof(MojoAttachMessagePipeToInvitationOptions) == 8, "MojoAttachMessagePipeToInvitationOptions has wrong size"); // Flags passed to |MojoExtractMessagePipeFromInvitation()| via // |MojoExtractMessagePipeFromInvitationOptions|. typedef uint32_t MojoExtractMessagePipeFromInvitationFlags; // No flags. Default behavior. #define MOJO_EXTRACT_MESSAGE_PIPE_FROM_INVITATION_FLAG_NONE \ ((MojoExtractMessagePipeFromInvitationFlags)0) // Options passed to |MojoExtractMessagePipeFromInvitation()|. struct MOJO_ALIGNAS(8) MojoExtractMessagePipeFromInvitationOptions { // The size of this structure, used for versioning. uint32_t struct_size; // See |MojoExtractMessagePipeFromInvitationFlags|. MojoExtractMessagePipeFromInvitationFlags flags; }; MOJO_STATIC_ASSERT( sizeof(MojoExtractMessagePipeFromInvitationOptions) == 8, "MojoExtractMessagePipeFromInvitationOptions has wrong size"); // Flags passed to |MojoSendInvitation()| via |MojoSendInvitationOptions|. typedef uint32_t MojoSendInvitationFlags; // No flags. Default behavior. #define MOJO_SEND_INVITATION_FLAG_NONE ((MojoSendInvitationFlags)0) // 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 ((MojoSendInvitationFlags)1) // Options passed to |MojoSendInvitation()|. struct MOJO_ALIGNAS(8) MojoSendInvitationOptions { // The size of this structure, used for versioning. uint32_t struct_size; // See |MojoSendInvitationFlags|. MojoSendInvitationFlags flags; // If |flags| includes |MOJO_SEND_INVITATION_FLAG_ISOLATED| then these fields // specify a name identifying the established isolated connection. There are // no restrictions on the value given. If |isolated_connection_name_length| is // non-zero, the system ensures that only one isolated process connection can // exist for the given name at any time. MOJO_POINTER_FIELD(const char*, isolated_connection_name); uint32_t isolated_connection_name_length; }; MOJO_STATIC_ASSERT(sizeof(MojoSendInvitationOptions) == 24, "MojoSendInvitationOptions has wrong size"); // Flags passed to |MojoAcceptInvitation()| via |MojoAcceptInvitationOptions|. typedef uint32_t MojoAcceptInvitationFlags; // No flags. Default behavior. #define MOJO_ACCEPT_INVITATION_FLAG_NONE ((MojoAcceptInvitationFlags)0) // Accept an isoalted invitation from the sender. See // |MOJO_SEND_INVITATION_FLAG_ISOLATED| for details. #define MOJO_ACCEPT_INVITATION_FLAG_ISOLATED ((MojoAcceptInvitationFlags)1) // Options passed to |MojoAcceptInvitation()|. struct MOJO_ALIGNAS(8) MojoAcceptInvitationOptions { // The size of this structure, used for versioning. uint32_t struct_size; // See |MojoAcceptInvitationFlags|. MojoAcceptInvitationFlags flags; }; MOJO_STATIC_ASSERT(sizeof(MojoAcceptInvitationOptions) == 8, "MojoAcceptInvitationOptions has wrong size"); #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. typedef void (*MojoProcessErrorHandler)( uintptr_t context, const struct MojoProcessErrorDetails* details); // 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); #ifdef __cplusplus } // extern "C" #endif #endif // MOJO_PUBLIC_C_SYSTEM_INVITATION_H_