1 /***************************************************************************
2 message.c - Class for a protocol messages
4 begin : Sun Mar 12 2006
5 copyright : (C) 2006 by Yannick Lecaillez, Avi Alkalay
7 ***************************************************************************/
9 /***************************************************************************
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the BSD License (revised). *
14 ***************************************************************************/
16 /***************************************************************************
18 * Class for messages, to be passed over a protocol line. *
20 ***************************************************************************/
50 #include "kdbprivate.h"
53 * @defgroup message Message
54 * @brief Encapsulate procedure call for IPC between libelektra-daemon and kdbd
58 * #include "message.h"
61 * Message is a flat struct (i.e: without pointer) which encapsulate a
62 * procedure with arguments. Its the basis class for elektra daemon IPC.
63 * a Message pointer contain the Message struct and the eventual serialized
64 * arguments. Here a in memory schematic representation:
66 * #|MESSAGE STRUCT|ARG0-SERIALIZED|ARGN-SERIALIZED|#
69 * where # is the boundaries of the memory space allocated for the Message.
70 * Message depends of serializer.
72 * Refer to @link protocol Protocol@endlink for sending/receiving message.
77 * Message constructor.
79 * Create a new message with associated arguments.
80 * Message is a serialized procedure and arguments targeted to be
81 * send throught a medium.
82 * Arguments are copied, so you could free these after using messageNew
87 * // Create a request containing key and integer as arguments
88 * msg = messageNew(MESSAGE_REQUEST, 1, DATATYPE_KEY, key,
89 * DATATYPE_INTEGER, &myInt,
93 * @param msgType Message type (request, reply, internal error)
94 * @param procedure Procedure ID
98 * @see messageExtractArgs()
100 * @return newly allocated Message (must be freed with messageDel()) or NULL if error occured
105 Message *messageNew(MessageType msgType, int procedure, ...)
113 ssize_t serializedSize;
115 /* Compute size of Message + serialized args */
116 size = sizeof(Message);
118 va_start(va, procedure);
119 type = va_arg(va, DataType);
121 while ( (type != DATATYPE_LAST) && (nbArgs < MSG_MAX_ARGS) ) {
122 serializedSize = serializeGetSize(type, va_arg(va, void *));
123 if ( serializedSize == -1 ) {
124 fprintf(stderr, "SerializedGetSize = -1 for args %d of type %d !\n", nbArgs, type);
128 size += serializedSize;
131 type = va_arg(va, DataType);
135 if ( nbArgs == MSG_MAX_ARGS ) {
140 /* Allocate some memory */
141 msg = (Message *) malloc(size);
145 /* Fill message struct */
146 memset(msg, 0, size);
148 msg->procId = procedure;
149 msg->nbArgs = nbArgs;
151 memset(msg->args, 0, sizeof(msg->args));
153 buf += sizeof(Message);
155 /* Add serialized args ... */
157 va_start(va, procedure);
158 type = va_arg(va, DataType);
159 while ( type != DATATYPE_LAST ) {
160 serializedSize = serialize(type, va_arg(va, void *), buf);
161 if ( serializedSize == -1 ) {
166 msg->args[nbArgs++] = type;
167 buf += serializedSize;
169 type = va_arg(va, DataType);
177 * Get type of a message
180 * @return Type of the message
185 MessageType messageGetType(const Message *msg)
193 * Get procedure of a message
196 * @return Type of the message
199 int messageGetProcedure(const Message *msg)
207 * Get number of arguments contained in a message
213 int messageGetNbArgs(const Message *msg)
221 * Extract arguments from a message
222 * This methods extract arguments contained from a message
223 * into the suite of arguments passed to this method
228 * ret = messageExtractArgs(msg, DATATYPE_KEY, key,
229 * DATATYPE_INTEGER, &myInt,
234 * @return 0 if Ok, -1 on error.
240 int messageExtractArgs(const Message *msg, ...)
245 ssize_t serializedSize;
250 /* Skip message struct */
251 buf = (const char *) msg;
252 buf += sizeof(Message);
254 /* Unserialize args */
257 type = va_arg(va, DataType);
258 while ( (type != DATATYPE_LAST) && (args < MSG_MAX_ARGS) ) {
259 if ( msg->args[args] != type ) {
265 serializedSize = unserialize(type, buf, va_arg(va, void *));
266 if ( serializedSize == -1 ) {
271 buf += serializedSize;
274 type = va_arg(va, DataType);
278 if ( args == MSG_MAX_ARGS ) {
288 * Free all memory took by this message.
289 * This doesn't free arguments passed when message was created.
291 * @param msg Message to delete
296 void messageDel(Message *msg)