Proper documentation of the C bindings for KBUS (libkbus) will live here. For the moment, here are some header files:
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 */
/*
* ***** 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);
/*
* 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:
/*
* ***** 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: