You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
457 lines
21 KiB
457 lines
21 KiB
// 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 <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.
|
|
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_
|