KBUS C bindings

Proper documentation of the C bindings for KBUS (libkbus) will live here. For the moment, here are some header files:

  • kbus/linux/kbus_defns.h - the kernel header file, which defines the various datastructures, the IOCTLs, and some useful macros and functions. This header file is used by the kernel, and also by user space programs (although in this latter case normally by including the libkbus header file).
  • libkbus/kbus.h - the main header file for libkbus. This include the kernel header file for you.
  • libkbux/limpet.h - the libkbus header file for Limpet code. Since Limpets are more normally used via the runlimpet application, this may or may not be of direct use.

kbus/linux/kbus_defns.h

Please be aware that the comments in this file are currently inaccurate, and scheduled to be rewritten. The datastructures are, of course, correct...

/* Kbus kernel module external headers
 *
 * This file provides the definitions (datastructures and ioctls) needed to
 * communicate with the KBUS character device driver.
 */

/*
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the KBUS Lightweight Linux-kernel mediated
 * message system
 *
 * The Initial Developer of the Original Code is Kynesim, Cambridge UK.
 * Portions created by the Initial Developer are Copyright (C) 2009
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Kynesim, Cambridge UK
 *   Tony Ibbs <tibs@tonyibbs.co.uk>
 *
 * Alternatively, the contents of this file may be used under the terms of the
 * GNU Public License version 2 (the "GPL"), in which case the provisions of
 * the GPL are applicable instead of the above.  If you wish to allow the use
 * of your version of this file only under the terms of the GPL and not to
 * allow others to use your version of this file under the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL.  If you do not delete the
 * provisions above, a recipient may use your version of this file under either
 * the MPL or the GPL.
 *
 * ***** END LICENSE BLOCK *****
 */

#ifndef _kbus_defns
#define _kbus_defns

#if !__KERNEL__ && defined(__cplusplus)
extern "C" {
#endif

#include <linux/types.h>
#if __KERNEL__
#include <linux/kernel.h>
#include <linux/ioctl.h>
#else
#include <stdint.h>
#include <sys/ioctl.h>
#endif

/*
 * A message id is made up of two fields.
 *
 * If the network id is 0, then it is up to us (KBUS) to assign the
 * serial number. In other words, this is a local message.
 *
 * If the network id is non-zero, then this message is presumed to
 * have originated from another "network", and we preserve both the
 * network id and the serial number.
 *
 * The message id {0,0} is special and reserved (for use by KBUS).
 */
struct kbus_msg_id {
        __u32 network_id;
        __u32 serial_num;
};

/*
 * kbus_orig_from is used for the "originally from" and "finally to" ids
 * in the message header. These in turn are used when messages are
 * being sent between KBUS systems (via KBUS "Limpets"). KBUS the kernel
 * module transmits them, unaltered, but does not use them (although
 * debug messages may report them).
 *
 * An "originally from" or "finally to" id is made up of two fields, the
 * network id (which indicates the Limpet, if any, that originally gated the
 * message), and a local id, which is the Ksock id of the original sender
 * of the message, on its local KBUS.
 *
 * If the network id is 0, then the "originally from" id is not being used.
 *
 * Limpets and these fields are discussed in more detail in the userspace
 * KBUS documentation - see http://kbus-messaging.org/ for pointers to
 * more information.
 */
struct kbus_orig_from {
        __u32 network_id;
        __u32 local_id;
};

/* When the user asks to bind a message name to an interface, they use: */
struct kbus_bind_request {
        __u32 is_replier;       /* are we a replier? */
        __u32 name_len;
        char *name;
};

/* When the user requests the id of the replier to a message, they use: */
struct kbus_bind_query {
        __u32 return_id;
        __u32 name_len;
        char *name;
};

/* When the user writes/reads a message, they use: */
struct kbus_message_header {
        /*
         * The guards
         * ----------
         *
         * * 'start_guard' is notionally "Kbus", and 'end_guard' (the 32 bit
         *   word after the rest of the message datastructure) is notionally
         *   "subK". Obviously that depends on how one looks at the 32-bit
         *   word. Every message datastructure shall start with a start guard
         *   and end with an end guard.
         *
         * These provide some help in checking that a message is well formed,
         * and in particular the end guard helps to check for broken length
         * fields.
         *
         * - 'id' identifies this particular message.
         *
         *   When a user writes a new message, they should set this to {0,0}.
         *   KBUS will then set a new message id for the message.
         *
         *   When a user reads a message, this will have been set by KBUS.
         *
         *   When a user replies to a message, they should copy this value
         *   into the 'in_reply_to' field, so that the recipient will know
         *   what message this was a reply to.
         *
         * - 'in_reply_to' identifies the message this is a reply to.
         *
         *   This shall be set to {0,0} unless this message *is* a reply to a
         *   previous message. In other words, if this value is non-0, then
         *   the message *is* a reply.
         *
         * - 'to' is who the message is to be sent to.
         *
         *   When a user writes a new message, this should normally be set
         *   to {0,0}, meaning "anyone listening" (but see below if "state"
         *   is being maintained).
         *
         *   When replying to a message, it shall be set to the 'from' value
         *   of the orginal message.
         *
         *   When constructing a request message (a message wanting a reply),
         *   the user can set it to a specific replier id, to produce a stateful
         *   request. This is normally done by copying the 'from' of a previous
         *   Reply from the appropriate replier. When such a message is sent,
         *   if the replier bound (at that time) does not have that specific
         *   id, then the send will fail.
         *
         *   Note that if 'to' is set, then 'orig_from' should also be set.
         *
         * - 'from' indicates who sent the message.
         *
         *   When a user is writing a new message, they should set this
         *   to {0,0}.
         *
         *   When a user is reading a message, this will have been set
         *   by KBUS.
         *
         *   When a user replies to a message, the reply should have its
         *   'to' set to the original messages 'from', and its 'from' set
         *   to {0,0} (see the "hmm" caveat under 'to' above, though).
         *
         * - 'orig_from' and 'final_to' are used when Limpets are mediating
         *   KBUS messages between KBUS devices (possibly on different
         *   machines). See the description by the datastructure definition
         *   above. The KBUS kernel preserves and propagates their values,
         *   but does not alter or use them.
         *
         * - 'extra' is currently unused, and KBUS will set it to zero.
         *   Future versions of KBUS may treat it differently.
         *
         * - 'flags' indicates the type of message.
         *
         *   When a user writes a message, this can be used to indicate
         *   that:
         *
         *   * the message is URGENT
         *   * a reply is wanted
         *
         *   When a user reads a message, this indicates if:
         *
         *   * the message is URGENT
         *   * a reply is wanted
         *
         *   When a user writes a reply, this field should be set to 0.
         *
         *   The top half of the 'flags' is not touched by KBUS, and may
         *   be used for any purpose the user wishes.
         *
         * - 'name_len' is the length of the message name in bytes.
         *
         *   This must be non-zero.
         *
         * - 'data_len' is the length of the message data in bytes. It may be
         *   zero if there is no data.
         *
         * - 'name' is a pointer to the message name. This should be null
         *   terminated, as is the normal case for C strings.
         *
         *   NB: If this is zero, then the name will be present, but after
         *   the end of this datastructure, and padded out to a multiple of
         *   four bytes (see kbus_entire_message). When doing this padding,
         *   remember to allow for the terminating null byte. If this field is
         *   zero, then 'data' shall also be zero.
         *
         * - 'data' is a pointer to the data. If there is no data (if
         *   'data_len' is zero), then this shall also be zero. The data is
         *   not touched by KBUS, and may include any values.
         *
         *   NB: If this is zero, then the data will occur immediately
         *   after the message name, padded out to a multiple of four bytes.
         *   See the note for 'name' above.
         *
         */
        __u32 start_guard;
        struct kbus_msg_id id;  /* Unique to this message */
        struct kbus_msg_id in_reply_to; /* Which message this is a reply to */
        __u32 to;               /* 0 (empty) or a replier id */
        __u32 from;             /* 0 (KBUS) or the sender's id */
        struct kbus_orig_from orig_from;/* Cross-network linkage */
        struct kbus_orig_from final_to; /* Cross-network linkage */
        __u32 extra;    /* ignored field - future proofing */
        __u32 flags;    /* Message type/flags */
        __u32 name_len; /* Message name's length, in bytes */
        __u32 data_len; /* Message length, also in bytes */
        char *name;
        void *data;
        __u32 end_guard;
};

#define KBUS_MSG_START_GUARD    0x7375624B
#define KBUS_MSG_END_GUARD      0x4B627573

/*
 * When a message is returned by 'read', it is actually returned using the
 * following datastructure, in which:
 *
 * - 'header.name' will point to 'rest[0]'
 * - 'header.data' will point to 'rest[(header.name_len+3)/4]'
 *
 * followed by the name (padded to 4 bytes, remembering to allow for the
 * terminating null byte), followed by the data (padded to 4 bytes) followed by
 * (another) end_guard.
 */
struct kbus_entire_message {
        struct kbus_message_header header;
        __u32 rest[];
};

/*
 * We limit a message name to at most 1000 characters (some limit seems
 * sensible, after all)
 */
#define KBUS_MAX_NAME_LEN       1000

/*
 * The length (in bytes) of the name after padding, allowing for a terminating
 * null byte.
 */
#define KBUS_PADDED_NAME_LEN(name_len)   (4 * ((name_len + 1 + 3) / 4))

/*
 * The length (in bytes) of the data after padding
 */
#define KBUS_PADDED_DATA_LEN(data_len)   (4 * ((data_len + 3) / 4))

/*
 * Given name_len (in bytes) and data_len (in bytes), return the
 * length of the appropriate kbus_entire_message_struct, in bytes
 *
 * Note that we're allowing for a zero byte after the end of the message name.
 *
 * Remember that "sizeof" doesn't count the 'rest' field in our message
 * structure.
 */
#define KBUS_ENTIRE_MSG_LEN(name_len, data_len)    \
        (sizeof(struct kbus_entire_message) + \
         KBUS_PADDED_NAME_LEN(name_len) + \
         KBUS_PADDED_DATA_LEN(data_len) + 4)

/*
 * The message name starts at entire->rest[0].
 * The message data starts after the message name - given the message
 * name's length (in bytes), that is at index:
 */
#define KBUS_ENTIRE_MSG_DATA_INDEX(name_len)     ((name_len+1+3)/4)
/*
 * Given the message name length (in bytes) and the message data length (also
 * in bytes), the index of the entire message end guard is thus:
 */
#define KBUS_ENTIRE_MSG_END_GUARD_INDEX(name_len, data_len)  \
        ((name_len+1+3)/4 + (data_len+3)/4)

/*
 * Find a pointer to the message's name.
 *
 * It's either the given name pointer, or just after the header (if the pointer
 * is NULL)
 */
static inline char *kbus_msg_name_ptr(const struct kbus_message_header
                                      *hdr)
{
        if (hdr->name) {
                return hdr->name;
        } else {
                struct kbus_entire_message *entire;
                entire = (struct kbus_entire_message *)hdr;
                return (char *)&entire->rest[0];
        }
}

/*
 * Find a pointer to the message's data.
 *
 * It's either the given data pointer, or just after the name (if the pointer
 * is NULL)
 */
static inline void *kbus_msg_data_ptr(const struct kbus_message_header
                                      *hdr)
{
        if (hdr->data) {
                return hdr->data;
        } else {
                struct kbus_entire_message *entire;
                __u32 data_idx;

                entire = (struct kbus_entire_message *)hdr;
                data_idx = KBUS_ENTIRE_MSG_DATA_INDEX(hdr->name_len);
                return (void *)&entire->rest[data_idx];
        }
}

/*
 * Find a pointer to the message's (second/final) end guard.
 */
static inline __u32 *kbus_msg_end_ptr(struct kbus_entire_message
                                         *entire)
{
        __u32 end_guard_idx =
                KBUS_ENTIRE_MSG_END_GUARD_INDEX(entire->header.name_len,
                                                entire->header.data_len);
        return (__u32 *) &entire->rest[end_guard_idx];
}

/*
 * Things KBUS changes in a message
 * --------------------------------
 * In general, KBUS leaves the content of a message alone. However, it does
 * change:
 *
 * - the message id (if id.network_id is unset - it assigns a new serial
 *   number unique to this message)
 * - the from id (if from.network_id is unset - it sets the local_id to
 *   indicate the Ksock this message was sent from)
 * - the KBUS_BIT_WANT_YOU_TO_REPLY bit in the flags (set or cleared
 *   as appropriate)
 * - the SYNTHETIC bit, which KBUS will always unset in a user message
 */

/*
 * Flags for the message 'flags' word
 * ----------------------------------
 * The KBUS_BIT_WANT_A_REPLY bit is set by the sender to indicate that a
 * reply is wanted. This makes the message into a request.
 *
 *     Note that setting the WANT_A_REPLY bit (i.e., a request) and
 *     setting 'in_reply_to' (i.e., a reply) is bound to lead to
 *     confusion, and the results are undefined (i.e., don't do it).
 *
 * The KBUS_BIT_WANT_YOU_TO_REPLY bit is set by KBUS on a particular message
 * to indicate that the particular recipient is responsible for replying
 * to (this instance of the) message. Otherwise, KBUS clears it.
 *
 * The KBUS_BIT_SYNTHETIC bit is set by KBUS when it generates a synthetic
 * message (an exception, if you will), for instance when a replier has
 * gone away and therefore a reply will never be generated for a request
 * that has already been queued.
 *
 *     Note that KBUS does not check that a sender has not set this
 *     on a message, but doing so may lead to confusion.
 *
 * The KBUS_BIT_URGENT bit is set by the sender if this message is to be
 * treated as urgent - i.e., it should be added to the *front* of the
 * recipient's message queue, not the back.
 *
 * Send flags
 * ==========
 * There are two "send" flags, KBUS_BIT_ALL_OR_WAIT and KBUS_BIT_ALL_OR_FAIL.
 * Either one may be set, or both may be unset.
 *
 *    If both bits are set, the message will be rejected as invalid.
 *
 *    Both flags are ignored in reply messages (i.e., messages with the
 *    'in_reply_to' field set).
 *
 * If both are unset, then a send will behave in the default manner. That is,
 * the message will be added to a listener's queue if there is room but
 * otherwise the listener will (silently) not receive the message.
 *
 *     (Obviously, if the listener is a replier, and the message is a request,
 *     then a KBUS message will be synthesised in the normal manner when a
 *     request is lost.)
 *
 * If the KBUS_BIT_ALL_OR_WAIT bit is set, then a send should block until
 * all recipients can be sent the message. Specifically, before the message is
 * sent, all recipients must have room on their message queues for this
 * message, and if they do not, the send will block until there is room for the
 * message on all the queues.
 *
 * If the KBUS_BIT_ALL_OR_FAIL bit is set, then a send should fail if all
 * recipients cannot be sent the message. Specifically, before the message is
 * sent, all recipients must have room on their message queues for this
 * message, and if they do not, the send will fail.
 */

/*
 * When a $.KBUS.ReplierBindEvent message is constructed, we use the
 * following to encapsulate its data.
 *
 * This indicates whether it is a bind or unbind event, who is doing the
 * bind or unbind, and for what message name. The message name is padded
 * out to a multiple of four bytes, allowing for a terminating null byte,
 * but the name length is the length without said padding (so, in C terms,
 * strlen(name)).
 *
 * As for the message header data structure, the actual data "goes off the end"
 * of the datastructure.
 */
struct kbus_replier_bind_event_data {
        __u32 is_bind;  /* 1=bind, 0=unbind */
        __u32 binder;   /* Ksock id of binder */
        __u32 name_len; /* Length of name */
        __u32 rest[];   /* Message name */
};

#if !__KERNEL__
#define BIT(num)                 (((unsigned)1) << (num))
#endif

#define KBUS_BIT_WANT_A_REPLY           BIT(0)
#define KBUS_BIT_WANT_YOU_TO_REPLY      BIT(1)
#define KBUS_BIT_SYNTHETIC              BIT(2)
#define KBUS_BIT_URGENT                 BIT(3)

#define KBUS_BIT_ALL_OR_WAIT            BIT(8)
#define KBUS_BIT_ALL_OR_FAIL            BIT(9)

/*
 * Standard message names
 * ======================
 * KBUS itself has some predefined message names.
 *
 * Synthetic Replies with no data
 * ------------------------------
 * These are sent to the original Sender of a Request when KBUS knows that the
 * Replier is not going to Reply. In all cases, you can identify which message
 * they concern by looking at the "in_reply_to" field:
 *
 * * Replier.GoneAway - the Replier has gone away before reading the Request.
 * * Replier.Ignored - the Replier has gone away after reading a Request, but
 *   before replying to it.
 * * Replier.Unbound - the Replier has unbound (as Replier) from the message
 *   name, and is thus not going to reply to this Request in its unread message
 *   queue.
 * * Replier.Disappeared - the Replier has disappeared when an attempt is made
 *   to send a Request whilst polling (i.e., after EAGAIN was returned from an
 *   earlier attempt to send a message). This typically means that the Ksock
 *   bound as Replier closed.
 * * ErrorSending - an unexpected error occurred when trying to send a Request
 *   to its Replier whilst polling.
 *
 * Synthetic Announcements with no data
 * ------------------------------------
 * * UnbindEventsLost - sent (instead of a Replier Bind Event) when the unbind
 *   events "set aside" list has filled up, and thus unbind events have been
 *   lost.
 */
#define KBUS_MSG_NAME_REPLIER_GONEAWAY          "$.KBUS.Replier.GoneAway"
#define KBUS_MSG_NAME_REPLIER_IGNORED           "$.KBUS.Replier.Ignored"
#define KBUS_MSG_NAME_REPLIER_UNBOUND           "$.KBUS.Replier.Unbound"
#define KBUS_MSG_NAME_REPLIER_DISAPPEARED       "$.KBUS.Replier.Disappeared"
#define KBUS_MSG_NAME_ERROR_SENDING             "$.KBUS.ErrorSending"
#define KBUS_MSG_NAME_UNBIND_EVENTS_LOST        "$.KBUS.UnbindEventsLost"

/*
 * Replier Bind Event
 * ------------------
 * This is the only message name for which KBUS generates data -- see
 * kbus_replier_bind_event_data. It is also the only message name which KBUS
 * does not allow binding to as a Replier.
 *
 * This is the message that is sent when a Replier binds or unbinds to another
 * message name, if the KBUS_IOC_REPORTREPLIERBINDS ioctl has been used to
 * request such notification.
 */
#define KBUS_MSG_NAME_REPLIER_BIND_EVENT        "$.KBUS.ReplierBindEvent"

#define KBUS_IOC_MAGIC  'k'     /* 0x6b - which seems fair enough for now */
/*
 * RESET: reserved for future use
 */
#define KBUS_IOC_RESET      _IO(KBUS_IOC_MAGIC,  1)
/*
 * BIND - bind a Ksock to a message name
 * arg: struct kbus_bind_request, indicating what to bind to
 * retval: 0 for success, negative for failure
 */
#define KBUS_IOC_BIND      _IOW(KBUS_IOC_MAGIC,  2, char *)
/*
 * UNBIND - unbind a Ksock from a message id
 * arg: struct kbus_bind_request, indicating what to unbind from
 * retval: 0 for success, negative for failure
 */
#define KBUS_IOC_UNBIND    _IOW(KBUS_IOC_MAGIC,  3, char *)
/*
 * KSOCKID - determine a Ksock's Ksock id
 *
 * The network_id for the current Ksock is, by definition, 0, so we don't need
 * to return it.
 *
 * arg (out): __u32, indicating this Ksock's local_id
 * retval: 0 for success, negative for failure
 */
#define KBUS_IOC_KSOCKID   _IOR(KBUS_IOC_MAGIC,  4, char *)
/*
 * REPLIER - determine the Ksock id of the replier for a message name
 * arg: struct kbus_bind_query
 *
 *    - on input, specify the message name to ask about.
 *    - on output, KBUS fills in the relevant Ksock id in the return_value,
 *      or 0 if there is no bound replier
 *
 * retval: 0 for success, negative for failure
 */
#define KBUS_IOC_REPLIER  _IOWR(KBUS_IOC_MAGIC,  5, char *)
/*
 * NEXTMSG - pop the next message from the read queue
 * arg (out): __u32, number of bytes in the next message, 0 if there is no
 *            next message
 * retval: 0 for success, negative for failure
 */
#define KBUS_IOC_NEXTMSG   _IOR(KBUS_IOC_MAGIC,  6, char *)
/*
 * LENLEFT - determine how many bytes are left to read of the current message
 * arg (out): __u32, number of bytes left, 0 if there is no current read
 *            message
 * retval: 1 if there was a message, 0 if there wasn't, negative for failure
 */
#define KBUS_IOC_LENLEFT   _IOR(KBUS_IOC_MAGIC,  7, char *)
/*
 * SEND - send the current message
 * arg (out): struct kbus_msg_id, the message id of the sent message
 * retval: 0 for success, negative for failure
 */
#define KBUS_IOC_SEND      _IOR(KBUS_IOC_MAGIC,  8, char *)
/*
 * DISCARD - discard the message currently being written (if any)
 * arg: none
 * retval: 0 for success, negative for failure
 */
#define KBUS_IOC_DISCARD    _IO(KBUS_IOC_MAGIC,  9)
/*
 * LASTSENT - determine the message id of the last message SENT
 * arg (out): struct kbus_msg_id, {0,0} if there was no last message
 * retval: 0 for success, negative for failure
 */
#define KBUS_IOC_LASTSENT  _IOR(KBUS_IOC_MAGIC, 10, char *)
/*
 * MAXMSGS - set the maximum number of messages on a Ksock read queue
 * arg (in): __u32, the requested length of the read queue, or 0 to just
 *           request how many there are
 * arg (out): __u32, the length of the read queue after this call has
 *            succeeded
 * retval: 0 for success, negative for failure
 */
#define KBUS_IOC_MAXMSGS  _IOWR(KBUS_IOC_MAGIC, 11, char *)
/*
 * NUMMSGS - determine how many messages are in the read queue for this Ksock
 * arg (out): __u32, the number of messages in the read queue.
 * retval: 0 for success, negative for failure
 */
#define KBUS_IOC_NUMMSGS   _IOR(KBUS_IOC_MAGIC, 12, char *)
/*
 * UNREPLIEDTO - determine the number of requests (marked "WANT_YOU_TO_REPLY")
 * which we still need to reply to.
 * arg(out): __u32, said number
 * retval: 0 for success, negative for failure
 */
#define KBUS_IOC_UNREPLIEDTO _IOR(KBUS_IOC_MAGIC, 13, char *)
/*
 * MSGONLYONCE - should we receive a message only once?
 *
 * This IOCTL tells a Ksock whether it should only receive a particular message
 * once, even if it is both a Replier and Listener for the message (in which
 * case it will always get the message as Replier, if appropriate), or if it is
 * registered as multiple Listeners for the message.
 *
 * arg(in): __u32, 1 to change to "only once", 0 to change to the default,
 * 0xFFFFFFFF to just return the current/previous state.
 * arg(out): __u32, the previous state.
 * retval: 0 for success, negative for failure (-EINVAL if arg in was not one
 * of the specified values)
 */
#define KBUS_IOC_MSGONLYONCE  _IOWR(KBUS_IOC_MAGIC, 14, char *)
/*
 * VERBOSE - should KBUS output verbose "printk" messages (for this device)?
 *
 * This IOCTL tells a Ksock whether it should output debugging messages. It is
 * only effective if the kernel module has been built with the VERBOSE_DEBUGGING
 * flag set.
 *
 * arg(in): __u32, 1 to change to "verbose", 0 to change to "quiet",
 * 0xFFFFFFFF to just return the current/previous state.
 * arg(out): __u32, the previous state.
 * retval: 0 for success, negative for failure (-EINVAL if arg in was not one
 * of the specified values)
 */
#define KBUS_IOC_VERBOSE  _IOWR(KBUS_IOC_MAGIC, 15, char *)

/*
 * NEWDEVICE - request another KBUS device (/dev/kbus<n>).
 *
 * The next device number (up to a maximum of 255) will be allocated.
 *
 * arg(out): __u32, the new device number (<n>)
 * retval: 0 for success, negative for failure
 */
#define KBUS_IOC_NEWDEVICE _IOR(KBUS_IOC_MAGIC, 16, char *)

/*
 * REPORTREPLIERBINDS - request synthetic messages announcing Replier
 * bind/unbind events.
 *
 * If this flag is set, then when someone binds or unbinds to a message name as
 * a Replier, KBUS will send out a synthetic Announcement of this fact.
 *
 * arg(in): __u32, 1 to change to "report", 0 to change to "do not report",
 * 0xFFFFFFFF to just return the current/previous state.
 * arg(out): __u32, the previous state.
 * retval: 0 for success, negative for failure (-EINVAL if arg in was not one
 * of the specified values)
 */
#define KBUS_IOC_REPORTREPLIERBINDS  _IOWR(KBUS_IOC_MAGIC, 17, char *)
/*
 * MAXMSGSIZE - set the maximum size of a KBUS message for this KBUS device.
 * This may not be set to less than 100, or more than
 * CONFIG_KBUS_ABS_MAX_MESSAGE_SIZE.
 * arg (in): __u32, the requested maximum message size, or 0 to just
 *           request what the current limit is, 1 to request the absolute
 *           maximum size.
 * arg (out): __u32, the maximum essage size after this call has
 *            succeeded
 * retval: 0 for success, negative for failure
 */
#define KBUS_IOC_MAXMSGSIZE _IOWR(KBUS_IOC_MAGIC, 18, char *)

/* If adding another IOCTL, remember to increment the next number! */
#define KBUS_IOC_MAXNR  18

#if !__KERNEL__ && defined(__cplusplus)
}
#endif

#endif /* _kbus_defns */

libkbus/kbus.h

/*
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the KBUS Lightweight Linux-kernel mediated
 * message system
 *
 * The Initial Developer of the Original Code is Kynesim, Cambridge UK.
 * Portions created by the Initial Developer are Copyright (C) 2009
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Kynesim, Cambridge UK
 *   Gareth Bailey <gb@kynesim.co.uk>
 *   Tony Ibbs <tibs@tonyibbs.co.uk>
 *
 * ***** END LICENSE BLOCK *****
 */

#ifndef _LKBUS_H_INCLUDED_
#define _LKBUS_H_INCLUDED_

#ifdef __cplusplus
extern "C" {
#endif

#include "linux/kbus_defns.h"

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>

// NOTE that the middle portion of this file is autogenerated from libkbus.c
// so that the function header comments and function prototypes may be
// automatically kept in-step. This allows me to treat the C file as the main
// specification of the functions it defines, and also to keep C header
// comments in the C file, which I find easier when keeping the comments
// correct as the code is edited.
//
// The Python script extract_hdrs.py is used to perform this autogeneration.
// It should transfer any C function marked as 'extern' and with a header
// comment (of the '/*...*...*/' form).

/*
 * In kernel modules (and thus in the kbus_defns.h header, which is used by the
 * KBUS kernel module) ``typedef`` is strongly discouraged. Therefore the KBUS
 * kernel module header does not provide a typedef for, well, anything.
 * However, in the outside C programming world, typedefs are often a good thing,
 * allowing simpler programming, so we provide some here.
 */

typedef struct kbus_msg_id              kbus_msg_id_t;
typedef struct kbus_orig_from           kbus_orig_from_t;
typedef struct kbus_bind_request        kbus_bind_request_t;
typedef struct kbus_bind_query          kbus_bind_query_t;

typedef struct kbus_message_header      kbus_message_t;

typedef struct kbus_entire_message      kbus_entire_message_t;

typedef struct kbus_replier_bind_event_data     kbus_replier_bind_event_data_t;

/** A Ksock is just a file descriptor, an integer, as returned by 'open'.
 */
typedef int kbus_ksock_t;

/*
 * Please, however, do consult the kbus_defns.h header file for many useful
 * definitions, and also some key functions, such as:
 *
 * * kbus_msg_name_ptr(msg)
 * * kbus_msg_data_ptr(msg)
 *
 * which are really what you want for extracting KBUS message name and data
 * from the message datastructures (regardless of whether they are pointy or
 * not).
 *
 * If you haven't read kbus_defns.h, you *are* missing important information.
 */

// The following are used in kbus_wait_for_message.
#define KBUS_KSOCK_READABLE 1
#define KBUS_KSOCK_WRITABLE 2

/* Ksock Functions */

/** @file
 *
 * Note that all of the functions here are non-blocking: there is no such
 * thing as a synchronous kbus socket (though there are wait() functions here
 * to emulate one).
 */

// -------- TEXT AFTER THIS AUTOGENERATED - DO NOT EDIT --------
// Autogenerated by extract_hdrs.py on 2013-01-16 (Wed 16 Jan 2013) at 11:47

/*
 * Open a Ksock.
 *
 * `device_number` indicates which KSock device to open, as
 * "/dev/kbus<device_number>".
 *
 * Which device numbers are available depends upon how many KBUS devices have
 * been initialised, either when the KBUS kernel module was installed, or by
 * use of `kbus_new_device()`.
 *
 * `flags` may be one of ``O_RDONLY``, ``O_WRONLY`` or ``O_RDWR``.
 *
 * Returns the file descriptor for the new Ksock, or a negative value on error.
 * The negative value will be ``-errno``.
 */
extern kbus_ksock_t kbus_ksock_open(uint32_t device_number,
                                    int      flags);

/*
 * Open a Ksock by device name. Since KBUS currrently only supports devices
 * of the for ``/dev/kbus<device_number>``, this function has no advantage
 * over `kbus_ksock_open``.
 *
 * `device_name` indicates which KSock device to open, as "/dev/kbus<device_number>",
 * where ``<device_number>`` is zero or more, depending on how many KBUS
 * devices are initialised.
 *
 * `flags` may be one of ``O_RDONLY``, ``O_WRONLY`` or ``O_RDWR``.
 *
 * Returns the file descriptor for the new Ksock, or a negative value on error.
 * The negative value will be ``-errno``.
 */
extern kbus_ksock_t kbus_ksock_open_by_name(const char *device_name,
                                            int         flags);

/*
 * Close a Ksock.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_ksock_close(kbus_ksock_t ksock);

/*
 * Bind the given message name to the specified Ksock.
 *
 * If `is_replier`, then bind as a Replier, otherwise as a Listener.
 *
 * Only one KSock at a time may be bound to a particular message as a Replier.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_ksock_bind(kbus_ksock_t         ksock,
                           const char          *name,
                           uint32_t             is_replier);

/*
 * Unbind the given message name to the specified Ksock.
 *
 * If `is_replier`, then unbind as a Replier, otherwise as a Listener.
 *
 * The unbinding must exactly match a previous binding (i.e., both message name
 * and `is_replier` must match).
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_ksock_unbind(kbus_ksock_t         ksock,
                             const char          *name,
                             uint32_t             is_replier);

/*
 * Return the internal (to KBUS) Ksock id for this Ksock.
 *
 * The Ksock id is a positive, non-zero number. It is used in message ``to``
 * and ``from`` fields.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_ksock_id(kbus_ksock_t   ksock,
                         uint32_t      *ksock_id);

/*
 * Indicate that we wish to start reading the next message.
 *
 * Each Ksock has an (internal to KBUS) "next message" list. This function
 * pops the next message from that list, and makes it the "being read" message.
 * If there was still data for an earlier "being read" message, this will be
 * thrown away.
 *
 * `message_length` is set to the length of the message - that is, the value
 * to be passed to a subsequent call of ``kbus_ksock_next_msg()`` - or 0 if
 * there is no next message.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_ksock_next_msg(kbus_ksock_t     ksock,
                               uint32_t        *message_length);

/*
 * Find out how many bytes of the "being read" message are still to be read.
 *
 * `len_left` is set to the remaining number of bytes, or 0 if there are no
 * more bytes in the "being read" message, or if there is no "being read"
 * message (i.e., ``kbus_ksock_next_msg()`` has not been called since the
 * last message was finished or discarded).
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_ksock_len_left(kbus_ksock_t   ksock,
                               uint32_t      *len_left);

/*
 * Determine the message id of the last message written on this Ksock.
 *
 * This will be {0,0} if there was no previous message.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_ksock_last_msg_id(kbus_ksock_t          ksock,
                                  kbus_msg_id_t        *msg_id);

/*
 * Find the Ksock id of the Replier for the given message name.
 *
 * `replier_ksock_id` will either be the Replier's Ksock id, or 0 if there
 * is no Replier bound for this message name.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_ksock_find_replier(kbus_ksock_t   ksock,
                                   const char    *name,
                                   uint32_t      *replier_ksock_id);

/*
 * Determine the number of (unread) messages that can be queued for this Ksock.
 *
 * If 'max_messages' is greater than 0, then KBUS will be asked to adjust the
 * read queue for this Ksock to length 'max_messages'.
 *
 * If 'max_messages' is 0, then it will be set to the current length of the
 * queue.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_ksock_max_messages(kbus_ksock_t   ksock,
                                   uint32_t      *max_messages);

/*
 * Find out how many (unread) messages are in the read queue for this Ksock.
 *
 * 'num_messages' will be set to the number of messages in the read queue.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_ksock_num_messages(kbus_ksock_t   ksock,
                                   uint32_t      *num_messages);

/*
 * Determine the number of (unread) messages queued for this Ksock.
 *
 * Returns the current (unread) message count for this Ksock, or a negative
 * number (``-errno``) for failure.
 */
extern int kbus_ksock_num_unreplied_to(kbus_ksock_t   ksock,
                                       uint32_t      *num_messages);

/*
 * Send the last written message.
 *
 * Used to send a message when all of it has been written.
 *
 * Once the messge has been sent, the message and any name/data pointed to may
 * be freed.
 *
 * `msg_id` returns the message id assigned to the message by KBUS.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_ksock_send(kbus_ksock_t         ksock,
                           kbus_msg_id_t       *msg_id);

/*
 * Discard the message being written.
 *
 * Indicates that KBUS should throw away the (partial) message that has been
 * written. If there is no current message being written (for instance, because
 * ``kbus_ksock_send()`` has just been called), then this function has no
 * effect.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_ksock_discard(kbus_ksock_t         ksock);

/*
 * Determine whether multiply-bound messages are only received once.
 *
 * Determine whether this Ksock should receive a particular message once, even
 * if it is both a Replier and Listener for the message, or if it is registered
 * more than once as a Listener for the message name.
 *
 * Note that in the case of a Request that the Ksock should reply to, it will
 * always get the Request, and it will be the Listener's version of the message
 * that will be "dropped".
 *
 * If `request` is 1, then only one copy of the message is wanted.
 *
 * If `request` is 0, then as many copies as implied by the bindings are wanted.
 *
 * If `request` is 0xFFFFFFFF, then the number of copies is not to be changed.
 * This may be used to query the current state of the "only once" flag for this
 * Ksock.
 *
 * Beware that setting this flag affects how messages are added to the Ksock's
 * message queue *as soon as it is set* - so changing it and then changing it
 * back "at once" is not (necessarily) a null operation.
 *
 * Returns 0 or 1, according to the state of the "only once" flag *before* this
 * function was called, or a negative number (``-errno``) for failure.
 */
extern int kbus_ksock_only_once(kbus_ksock_t   ksock,
                                uint32_t       request);

/*
 * Determine whether Replier bind/unbind events should be reported.
 *
 * If `request` is 1, then each time a Ksock binds or unbinds as a Replier,
 * a Replier bind/unbind event should be sent (a "$.KBUS.ReplierBindEvent"
 * message).
 *
 * If `request` is 0, then Replier bind/unbind events should not be sent.
 *
 * If `request` is 0xFFFFFFFF, then the current state should not be changed.
 * This may be used to query the current state of the "send Replier bind event"
 * flag.
 *
 * Note that although this call is made via an individual Ksock, it affects the
 * behaviour of the entire KBUS device to which this Ksock is attached.
 *
 * Returns 0 or 1, according to the state of the "send Replier bind event" flag
 * *before* this function was called, or a negative number (``-errno``) for
 * failure.
 */
extern int kbus_ksock_report_replier_binds(kbus_ksock_t       ksock,
                                           uint32_t           request);

/*
 * Request verbose kernel module messages.
 *
 * KBUS writes message via the normal kernel module mechanisms (which may be
 * inspected, for instance, via the ``dmesg`` command). Normal output is meant
 * to be reasonably minimal. Verbose messages can be useful for debugging the
 * kernel module.
 *
 * If `request` is 1, then verbose kernel messages are wanted.
 *
 * If `request` is 0, then verbose kernel messages are not wanted.
 *
 * If `request` is 0xFFFFFFFF, then the current state should not be changed.
 * This may be used to query the current state of the "verbose" flag.
 *
 * Note that although this call is made via an individual Ksock, it affects the
 * behaviour of the entire KBUS kernel module.
 *
 * Returns 0 or 1, according to the state of the "verbose" flag *before* this
 * function was called, or a negative number (``-errno``) for failure.
 */
extern int kbus_ksock_kernel_module_verbose(kbus_ksock_t       ksock,
                                            uint32_t           request);

/*
 * Request the KBUS kernel module to create a new device (``/dev/kbus<n>``).
 *
 * `device_number` is the ``<n>`` for the new device.
 *
 * Note that it takes the kernel's hotplugging mechanisms a little while to
 * notice/activate the device, so do not expect it to be available immediately
 * on return.
 *
 * Note that although this call is made via an individual Ksock, it affects the
 * behaviour of the entire KBUS kernel module.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_ksock_new_device(kbus_ksock_t  ksock,
                                 uint32_t     *device_number);

/*
 * Wait until either the Ksock may be read from or written to.
 *
 * Returns when there is data to be read from the Ksock, or the Ksock
 * may be written to.
 *
 * `wait_for` indicates what to wait for. It should be set to
 * ``KBUS_SOCK_READABLE``, ``KBUS_SOCK_WRITABLE``, or the two "or"ed together,
 * as appropriate.
 *
 * This is a convenience routine for when polling indefinitely on a Ksock is
 * appropriate. It is not intended as a generic routine for any more
 * complicated situation, when specific "poll" (or "select") code should be
 * written.
 *
 * Returns ``KBUS_SOCK_READABLE``, ``KBUS_SOCK_WRITABLE``, or the two "or"ed
 * together to indicate which operation is ready, or a negative number
 * (``-errno``) for failure.
 */
extern int kbus_wait_for_message(kbus_ksock_t  ksock,
                                 int           wait_for);

/*
 * Read a message of length `msg_len` bytes from this Ksock.
 *
 * It is assumed that `msg_len` was returned by a previous call of
 * ``kbus_ksock_next_msg()``. It must be large enough to cause the entire
 * message to be read.
 *
 * `msg` is the message read. This will be an "entire" message, and should be
 * freed by the caller when no longer needed.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 * Specifically, -EBADMSG will be returned if the underlying ``read``
 * returned 0.
 */
extern int kbus_ksock_read_msg(kbus_ksock_t      ksock,
                               kbus_message_t  **msg,
                               size_t            msg_len);

/*
 * Read the next message from this Ksock.
 *
 * This is equivalent to a call of ``kbus_ksock_next_msg()`` followed by a call
 * of ``kbus_ksock_read_msg()``.
 *
 * If there is no next message, ``msg`` will be NULL.
 *
 * If there is a next message, then ``msg`` will be the message read. This will
 * be an "entire" message, and should be freed by the caller when no longer
 * needed.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_ksock_read_next_msg(kbus_ksock_t          ksock,
                                    kbus_message_t      **msg);

/*
 * Write the given message to this Ksock. Does not send it.
 *
 * The `msg` may be an "entire" or "pointy" message.
 *
 * If the `msg` is a "pointy" message, then the name and any data must not be
 * freed until the message has been sent (as the pointers are only "followed"
 * when the message is sent).
 *
 * It is normally easier to use ``kbus_ksock_send_msg()``.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_ksock_write_msg(kbus_ksock_t             ksock,
                                const kbus_message_t    *msg);

/*
 * Write data to the Ksock. Does not send.
 *
 * This may be used to write message data in parts. It is normally better to use
 * the "whole message" routines.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_ksock_write_data(kbus_ksock_t    ksock,
                                 uint8_t        *data,
                                 size_t          data_len);

/*
 * Write and send a message on the given Ksock.
 *
 * This combines the "write" and "send" functions into one call, and is the
 * normal way to send a message.
 *
 * The `msg` may be an "entire" or "pointy" message.
 *
 * Once the message has been sent, the message and any name/data pointed to may
 * be freed.
 *
 * `msg_id` returns the message id assigned to the message by KBUS.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_ksock_send_msg(kbus_ksock_t             ksock,
                               const kbus_message_t    *msg,
                               kbus_msg_id_t           *msg_id);

/*
 * Create a message (specifically, a "pointy" message).
 *
 * Note that the message name and data are not copied, and thus should not be
 * freed until the message has been sent (with ``kbus_ksock_send_msg()``).
 *
 * `msg` is the new message, as created by this function.
 *
 * `name` is the name for the message, and `name_len` the length of the name
 * (the number of characters in the name). A message name is required.
 *
 * 'data' is the data for this message, or NULL if there is no data. `data_len`
 * is then the length of the data, in bytes.
 *
 * `flags` may be any KBUS message flags required. Most messages with flags set
 * can more easily be created by one of the other message creation routines.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_msg_create(kbus_message_t **msg,
                           const char *name,
                           uint32_t name_len, /* bytes  */
                           const void *data,
                           uint32_t data_len, /* bytes */
                           uint32_t flags);

/*
 * Create an "entire" message.
 *
 * Copies are taken of both `name` and `data` (and placed at the end of the
 * message datastructure).
 *
 * Unless you need to be able to free the name and/or data before sending
 * the message, it is more usual to use ``kbus_msg_create()`` instead.
 *
 * `msg` is the new message, as created by this function.
 *
 * `name` is the name for the message, and `name_len` the length of the name
 * (the number of characters in the name). A message name is required. The
 * name will be copied when the message is created.
 *
 * 'data' is the data for this message, or NULL if there is no data. `data_len`
 * is then the length of the data, in bytes. The data will be copied when the
 * message is created.
 *
 * `flags` may be any KBUS message flags required. Most messages with flags set
 * can more easily be created by one of the other message creation routines.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_msg_create_entire(kbus_message_t        **msg,
                                  const char             *name,
                                  uint32_t                name_len, /* bytes  */
                                  const void             *data,
                                  uint32_t                data_len, /* bytes */
                                  uint32_t                flags);

/*
 * Create a Request (specifically, a "pointy" Request message).
 *
 * Note that the message name and data are not copied, and thus should not be
 * freed until the message has been sent (with ``kbus_ksock_send_msg()``).
 *
 * `msg` is the new message, as created by this function.
 *
 * `name` is the name for the message, and `name_len` the length of the name
 * (the number of characters in the name). A message name is required.
 *
 * 'data' is the data for this message, or NULL if there is no data. `data_len`
 * is then the length of the data, in bytes.
 *
 * `flags` may be any KBUS message flags required. These will be set on the
 * message, and then (after that) the KBUS_BIT_WANT_A_REPLY flag will be set
 * to make the new message a Request.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_msg_create_request(kbus_message_t **msg,
                                   const char *name,
                                   uint32_t name_len, /* bytes  */
                                   const void *data,
                                   uint32_t data_len, /* bytes */
                                   uint32_t flags);

/*
 * Create an "entire" Request message.
 *
 * This is identical in behaviour to ``kbus_msg_create_request()``, except
 * that an "entire" message is created, and thus both the message name and data
 * are copied. This means that the original `name` and `data` may be freed as
 * soon as the `msg` has been created.
 *
 * Unless you need to be able to free the name and/or data before sending
 * the message, it is more usual to use ``kbus_msg_create_request()`` instead.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_msg_create_entire_request(kbus_message_t        **msg,
                                          const char             *name,
                                          uint32_t                name_len, /* bytes  */
                                          const void             *data,
                                          uint32_t                data_len, /* bytes */
                                          uint32_t                flags);

/*
 * Create a Reply message, based on a previous Request.
 *
 * This is a convenience mechanism for creating the Reply to a previous
 * Request.
 *
 * The Request must have been marked as wanting this particular recipient to
 * reply to it (i.e., ``kbus_msg_wants_us_to_reply()`` returns true). If this
 * is not so, -EBADMSG will be returned.
 *
 * `msg` is the new Reply message. `in_reply_to` is the Request message for
 * which a Reply is wanted.
 *
 * The message name for the new message will be taken from the old message.
 *
 * The 'to' field for the new message will be set to the 'from' field in the old.
 *
 * The 'in_reply_to' field for the new message will be set to the message id of the old.
 *
 * 'data' is the data for the new message, or NULL if there is none. 'data_len'
 * is the length of the data, in bytes.
 *
 * As normal, the message name and data should not be freed until `msg` has
 * been sent. In the normal case, where `in_reply_to` is an "entire" message
 * read from KBUS, this means that `in_reply_to` and `data` should not be
 * freed, since the message name "inside" `in_reply_to` is being referenced.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_msg_create_reply_to(kbus_message_t **msg,
                                    const kbus_message_t *in_reply_to,
                                    const void *data,
                                    uint32_t data_len, /* bytes */
                                    uint32_t flags);

/*
 * Create an "entire" Reply message, based on a previous Request.
 *
 * This is identical in behaviour to ``kbus_msg_create_reply_to()``, except
 * that an "entire" message is created, and thus both the message name and data
 * are copied. This means that the original (`in_reply_to`) message and the
 * `data` may be freed as soon as the `msg` has been created.
 *
 * Unless you need to be able to free the original message and/or data before
 * sending * the message, it is more usual to use
 * ``kbus_msg_create_reply_to()`` instead.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_msg_create_entire_reply_to(kbus_message_t          **msg,
                                           const kbus_message_t     *in_reply_to,
                                           const void               *data,
                                           uint32_t                  data_len, /* bytes */
                                           uint32_t                  flags);

/*
 * Create a Stateful Request message, based on a previous Reply or Request.
 *
 * This is a convenience mechanism for creating a Stateful Request message
 * (a Request which must be delivered to a particular Ksock).
 *
 * `msg` is the new Stateful Request message.
 *
 * `earlier_msg` is either a Reply message from the desired Ksock, or a
 * previous Stateful Request to the same Ksock.
 *
 * If the earlier message is a Reply, then the 'to' and 'final_to' fields for
 * the new message will be set to the 'from' and 'orig_from' fields in the old.
 *
 * If the earlier message is a Stateful Request, then the 'to' and 'final_to'
 * fields for the new message will be copied from the old.
 *
 * If the earlier message is neither a Reply nor a Stateful Request, then
 * -EBADMSG will be returned.
 *
 * 'name' is the name for the new message, and 'name_len' is the length of that
 * name.
 *
 * 'data' is the data for the new message, or NULL if there is none. 'data_len'
 * is the length of the data, in bytes.
 *
 * 'flags' is any KBUS flags to set on the message (flags will not be copied
 * from the earlier message).
 *
 * As normal, the message name and data should not be freed until `msg` has
 * been sent. `earlier_msg` may be freed after this call has completed, as
 * any necessary data will have been copied from it.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_msg_create_stateful_request(kbus_message_t         **msg,
                                            const kbus_message_t    *earlier_msg,
                                            const char          *name,
                                            uint32_t             name_len,
                                            const void          *data,
                                            uint32_t             data_len, /* bytes */
                                            uint32_t             flags);

/*
 * Create an "entire" Stateful Request message, based on a previous Reply or
 * Request.
 *
 * This is identical in behaviour to ``kbus_msg_create_stateful_request()``,
 * except that an "entire" message is created, and thus both the message name
 * and data are copied. This means that both the `name` and the `data` may be
 * freed as soon as the `msg` has been created.
 *
 * Unless you need to be able to free the name and/or data before sending
 * the message, it is more usual to use ``kbus_msg_create_statefule_request()``
 * instead.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_msg_create_entire_stateful_request(kbus_message_t       **msg,
                                                   const kbus_message_t  *earlier_msg,
                                                   const char            *name,
                                                   uint32_t               name_len,
                                                   const void            *data,
                                                   uint32_t               data_len, /* bytes */
                                                   uint32_t               flags);

/*
 * Delete a message datastructure.
 *
 * Does nothing if `msg_p` is NULL, or `*msg_p` is NULL.
 *
 * Frees the message datastructure, but does not free any name or data that is
 * pointed to.
 */
extern void kbus_msg_delete(kbus_message_t **msg_p);

/*
 * Delete a message datastructure, and any name/data it points to.
 *
 * Does nothing if `msg_p` is NULL, or `*msg_p` is NULL.
 *
 * Frees the message datastructure. If the message is "pointy", also
 * frees the message name and any message data.
 *
 * Caveat: do not pass this an "entire" message which has had its "name"
 * and/or "data" pointers set to point "inside" itself, to the name and
 * data at the end of the "entire" message. Really, it will end very badly
 * (and you probably shouldn't have done that, anyway).
 */
extern void kbus_msg_delete_all(kbus_message_t **msg_p);

/*
 * Determine the size of a KBUS message.
 *
 * For a "pointy" message, returns the size of the message header.
 *
 * For an "entire" message, returns the size of the entire message.
 *
 * In either case, this is the length of data that would (for instance)
 * be written to a Ksock to actually write the message. In other words::
 *
 *   int len, rv;
 *   len = kbus_msg_sizeof(&msg);
 *   rv = kbus_ksock_write_data(ksock, &msg, len);
 *   if (rv < 0) return rv;
 *
 * is the "low level" equivalent of::
 *
 *   int rv = kbus_ksock_write_msg(ksock, &msg);
 *   if (rv < 0) return rv;
 *
 * Returns the length of 'msg', as described above.
 */
extern int kbus_msg_sizeof(const kbus_message_t *msg);

/*
 * A convenience routine to split the data of a Replier bind event.
 *
 * Replier bind events contain the following information:
 *
 * * `is_replier` is true if the event was a "bind", false it if was an
 *   "unbind".
 * * `binder` is the Ksock id of the binder.
 * * `name` is the name of the message that was being (un)bound.
 *
 * Note that `name` is a copy of the name (from the original `msg`), so that
 * the user may free the original message immediately. Clearly this copy will
 * also need freeing when finished with.
 *
 * Returns 0 for success, or a negative number (``-errno``) for failure.
 */
extern int kbus_msg_split_bind_event(const kbus_message_t  *msg,
                                     uint32_t              *is_bind,
                                     uint32_t              *binder,
                                     char                 **name);

/*
 * Print out a representation of a message.
 *
 * `stream` is the output stream to print to -- typically stdout.
 *
 * Does not print a newline.
 */
extern void kbus_msg_print(FILE                 *stream,
                           const kbus_message_t *msg);


#define KBUS_MSG_PRINT_FLAGS_ABBREVIATE (1<<0)

/*
 * Print out a representation of a message.
 *
 * `stream` is the output stream to print to -- typically stdout.
 *
 * Does not print a newline.
 *
 * flags is an OR of KBUS_MSG_PRINT_FLAGS_XXX.
 */
extern void kbus_msg_print2(FILE                 *stream,
                            const kbus_message_t *msg, 
                            unsigned int flags);

/*
 * Print out (on stdout) information about a message.
 *
 * If `dump_data` is true, also print out the message data (in several forms).
 */
extern void kbus_msg_dump(const kbus_message_t *msg,
                          int                   dump_data);
// -------- TEXT BEFORE THIS AUTOGENERATED - DO NOT EDIT --------

/*
 * Check if a message is "entire".
 *
 * Returns true if the message is "entire", false if it is "pointy".
 * Strongly assumes the message is well-structured.
 */
static inline int kbus_msg_is_entire(const kbus_message_t     *msg)
{
  return msg->name == NULL;
}

/*
 * Check if a message is a Reply.
 */
static inline int kbus_msg_is_reply(const kbus_message_t    *msg)
{
  return msg->in_reply_to.network_id != 0 ||
         msg->in_reply_to.serial_num != 0;
}

/*
 * Check if a message is a Request.
 */
static inline int kbus_msg_is_request(const kbus_message_t      *msg)
{
  return (msg->flags & KBUS_BIT_WANT_A_REPLY) != 0;
}

/*
 * Check if a message is a Stateful Request.
 */
static inline int kbus_msg_is_stateful_request(const kbus_message_t      *msg)
{
  return (msg->flags & KBUS_BIT_WANT_A_REPLY) && (msg->to != 0);
}

/*
 * Check if a message is a Request to which we should reply.
 */
static inline int kbus_msg_wants_us_to_reply(const kbus_message_t       *msg)
{
  return (msg->flags & KBUS_BIT_WANT_A_REPLY) &&
         (msg->flags & KBUS_BIT_WANT_YOU_TO_REPLY);
}

/*
 * Compare two message ids.
 *
 * Returns -1 if id1 < id2, 0 if id1 == id2, +1 if id1 > id2.
 */
static inline int kbus_msg_compare_ids(const kbus_msg_id_t  *id1,
                                       const kbus_msg_id_t  *id2)
{
  if (id1->network_id == id2->network_id) {
    if (id1->serial_num == id2->serial_num)
      return 0;
    else if (id1->serial_num < id2->serial_num)
      return -1;
    else
      return 1;
  } else if (id1->network_id < id2->network_id)
    return -1;
  else
    return 1;
}

#ifdef __cplusplus
}
#endif

#endif /* _LKBUS_H_INCLUDED_ */

// Local Variables:
// tab-width: 8
// indent-tabs-mode: nil
// c-basic-offset: 2
// End:
// vim: set tabstop=8 shiftwidth=2 softtabstop=2 expandtab:

libkbus/limpet.h

/*
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the KBUS Lightweight Linux-kernel mediated
 * message system
 *
 * The Initial Developer of the Original Code is Kynesim, Cambridge UK.
 * Portions created by the Initial Developer are Copyright (C) 2010
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Kynesim, Cambridge UK
 *   Tony Ibbs <tibs@tonyibbs.co.uk>
 *
 * ***** END LICENSE BLOCK *****
 */

#ifndef _LIMPET_H_INCLUDED_
#define _LIMPET_H_INCLUDED_

#ifdef __cplusplus
extern "C" {
#endif

// NOTE that the middle portion of this file is autogenerated from limpet.c
// so that the function header comments and function prototypes may be
// automatically kept in-step. This allows me to treat the C file as the main
// specification of the functions it defines, and also to keep C header
// comments in the C file, which I find easier when keeping the comments
// correct as the code is edited.
//
// The Python script extract_hdrs.py is used to perform this autogeneration.
// It should transfer any C function marked as 'extern' and with a header
// comment (of the '/*...*...*/' form).

/*
 * The information needed to transform KBUS messages for Limpets:
 *
 * 1. after reading from KBUS and before writing to the other Limpet
 * 2. after receiving from the other Limpet and before writing to KBUS
 *
 * This is created by a call to kbus_limpet_new_context(), and freed
 * by a call to kbus_limpet_free_context().
 */
struct kbus_limpet_context;
typedef struct kbus_limpet_context kbus_limpet_context_t;


/*
 * Length of an array sufficient to hold the parts of a message header that
 * we need to send to/receive from the other Limpet.
 */
#define KBUS_SERIALISED_HDR_LEN 16

/*
 * Limpet specific messages.
 *
 * The "RemoteError" message has an error number appended to its name.
 */
#define KBUS_MSG_NOT_SAME_KSOCK         "$.KBUS.Replier.NotSameKsock"
#define KBUS_MSG_REMOTE_ERROR_PREFIX    "$.KBUS.RemoteError."

// -------- TEXT AFTER THIS AUTOGENERATED - DO NOT EDIT --------
// Autogenerated by extract_hdrs.py on 2013-01-16 (Wed 16 Jan 2013) at 11:47

/*
 * Given a KBUS message, set the `result` array to its content, suitable for
 * sending across the network
 *
 * Ignores the message's name and data pointers.
 *
 * Thus we end up with::
 *
 *  result[0]  = msg->start_guard
 *  result[1]  = msg->id.network_id
 *  result[2]  = msg->id.serial_num
 *  result[3]  = msg->in_reply_to.network_id
 *  result[4]  = msg->in_reply_to.serial_num
 *  result[5]  = msg->to
 *  result[6]  = msg->from
 *  result[7]  = msg->orig_from.network_id
 *  result[8]  = msg->orig_from.local_id
 *  result[9]  = msg->final_to.network_id
 *  result[10] = msg->final_to.local_id
 *  result[11] = msg->extra
 *  result[12] = msg->flags
 *  result[13] = msg->name_len
 *  result[14] = msg->data_len
 *  result[15] = msg->end_guard
 */
extern void kbus_serialise_message_header(kbus_message_t *msg,
                                          uint32_t        result[KBUS_SERIALISED_HDR_LEN]);

/*
 * Given a serialised message header from the network, set the message's header
 *
 * Leaves the message's name and data pointers unset (NULL).
 */
extern void kbus_unserialise_message_header(uint32_t        serial[KBUS_SERIALISED_HDR_LEN],
                                            kbus_message_t *msg);

/*
 * Prepare for Limper handling on the given Ksock, and return a Limpet context.
 *
 * This function binds to the requested message name, sets up Replier Bind
 * Event messages, and requests only one copy of each message.
 *
 * - 'ksock' is the Ksock which is to this end of our Limpet. It must be open
 *   for read and write.
 * - 'network_id' is the network id which identifies this Limpet. It is set in
 *   message ids when we are forwarding a message to the other Limpet. It must
 *   be greater than zero.
 * - 'other_network_id' is the network if of the other Limpet. It must not be
 *   the same as our_network_id. It must be greater than zero.
 * - 'message_name' is the message name that this Limpet will bind to, and
 *   forward. This will normally be a wildcard, and defaults to "$.*". Other
 *   messages will treated as ignorable. A copy is taken of this string.
 * - if 'verbosity' is:
 *
 *   * 0, we are as silent as possible
 *   * 1, we announce ourselves, and output any error/warning messages
 *   * 2 (or higher), we output information about each message as it is
 *     processed.
 *
 * 'context' is the Limpet context, allocated by this function. Free it with
 * ksock_limpet_free_context() when it is no longer required.
 *
 * Returns 0 if all goes well, a negative number (``-errno``) for
 * failure (in particular, returns -EBADMSG if 'message_name' is NULL or too
 * short).
 */
extern int kbus_limpet_new_context(kbus_ksock_t              ksock,
                                   uint32_t                  network_id,
                                   uint32_t                  other_network_id,
                                   char                     *message_name,
                                   uint32_t                  verbosity,
                                   kbus_limpet_context_t   **context);

/*
 * Change the verbosity level for a Limpet context
 */
extern void kbus_limpet_set_verbosity(kbus_limpet_context_t *context,
                                      uint32_t               verbosity);

/*
 * Free a Kbus Limpet context that is no longer required.
 *
 * After freeing 'context', it will be set to a pointer to NULL.
 *
 * If 'context' is is already a pointer to NULL, this function does nothing.
 */
extern void kbus_limpet_free_context(kbus_limpet_context_t  **context);

/*
 * Given a message read from KBUS, amend it for sending to the other Limpet.
 *
 * Returns:
 *
 * * 0 if the message has successfully been amended, and should be sent to
 *   KBUS.
 * * 1 if the message is not of interest and should be ignored.
 * * A negative number (``-errno``) for failure.
 */
extern int kbus_limpet_amend_msg_from_kbus(kbus_limpet_context_t *context,
                                           kbus_message_t        *msg);

/*
 * Given a message read from the other Limpet, amend it for sending to KBUS.
 *
 * * 'context' describes the Limpet environment
 * * 'msg' is the message to be amended. It will be changed appropriately.
 *   Note that the message data will never be touched.
 * * 'error' will be NULL or an error message to be sent to the other Limpet.
 *   In the latter case, it is up to the caller to free it.
 *
 * Returns:
 *
 * * 0 if the message has successfully been amended, and should be sent to
 *   KBUS.
 * * 1 if the message is not of interest and should be ignored.
 * * 2 if an error occurred, and the 'error' message should be sent (back)
 *   to the other Limpet (in this case the original error should not be
 *   send to KBUS).
 * * A negative number (``-errno``) for failure.
 */
extern int kbus_limpet_amend_msg_to_kbus(kbus_limpet_context_t  *context,
                                         kbus_message_t      *msg,
                                         kbus_message_t     **error);

/*
 * Convert the data of a Replier Bind Event message to network order.
 *
 * Does not check the message name, so please only call it for
 * messages called "$.ReplierBindEvent" (KBUS_MSG_NAME_REPLIER_BIND_EVENT).
 */
extern void kbus_limpet_ReplierBindEvent_hton(kbus_message_t  *msg);

/*
 * Convert the data of a Replier Bind Event message to host order.
 *
 * Does not check the message name, so please only call it for
 * messages called "$.ReplierBindEvent" (KBUS_MSG_NAME_REPLIER_BIND_EVENT).
 */
extern void kbus_limpet_ReplierBindEvent_ntoh(kbus_message_t  *msg);

/*
 * If sending to our Ksock failed, maybe generate a message suitable for
 * sending back to the other Limpet.
 *
 * 'msg' is the message we tried to send, 'errnum' is the error returned
 * by KBUS when it tried to send the message.
 *
 * 'error' is the new error message. The caller is responsible for freeing
 * 'error'.
 *
 * An 'error' message will be generated if the original message was a Request,
 * and (at time of writing) not otherwise.
 *
 * Returns
 *
 * * 0 if all goes well (in which case 'error' is non-NULL).
 * * 1 if there is no need to send an error to the other Limpet, 'error' is
 *   NULL, and the event should be ignored.
 * * A negative number (``-errno``) for failure.
 */
extern int kbus_limpet_could_not_send_to_kbus_msg(kbus_limpet_context_t  *context,
                                                  kbus_message_t      *msg,
                                                  int                  errnum,
                                                  kbus_message_t     **error);
// -------- TEXT BEFORE THIS AUTOGENERATED - DO NOT EDIT --------

#ifdef __cplusplus
}
#endif

#endif /* _LIMPET_H_INCLUDED_ */

// Local Variables:
// tab-width: 8
// indent-tabs-mode: nil
// c-basic-offset: 2
// End:
// vim: set tabstop=8 shiftwidth=2 softtabstop=2 expandtab: