1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-message.c DBusMessage object
4 * Copyright (C) 2002 Red Hat Inc.
6 * Licensed under the Academic Free License version 1.2
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "dbus-internals.h"
25 #include "dbus-message.h"
26 #include "dbus-message-internal.h"
27 #include "dbus-memory.h"
28 #include "dbus-list.h"
32 * @defgroup DBusMessageInternals DBusMessage implementation details
33 * @ingroup DBusInternals
34 * @brief DBusMessage private implementation details.
36 * The guts of DBusMessage and its methods.
42 * The largest-length message we allow
44 * @todo match this up with whatever the protocol spec says.
46 #define _DBUS_MAX_MESSAGE_LENGTH (_DBUS_INT_MAX/16)
49 * @brief Internals of DBusMessage
51 * Object representing a message received from or to be sent to
52 * another application. This is an opaque object, all members
57 int refcount; /**< Reference count */
59 DBusString header; /**< Header network data, stored
60 * separately from body so we can
61 * independently realloc it.
64 DBusString body; /**< Body network data. */
66 unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
70 * Gets the data to be sent over the network for this message.
71 * The header and then the body should be written out.
72 * This function is guaranteed to always return the same
73 * data once a message is locked (with _dbus_message_lock()).
75 * @param message the message.
76 * @param header return location for message header data.
77 * @param body return location for message body data.
80 _dbus_message_get_network_data (DBusMessage *message,
81 const DBusString **header,
82 const DBusString **body)
84 _dbus_assert (message->locked);
86 *header = &message->header;
87 *body = &message->body;
91 * Locks a message. Allows checking that applications don't keep a
92 * reference to a message in the outgoing queue and change it
93 * underneath us. Messages are locked when they enter the outgoing
94 * queue (dbus_connection_send_message()), and the library complains
95 * if the message is modified while locked.
97 * @param message the message to lock.
100 _dbus_message_lock (DBusMessage *message)
102 message->locked = TRUE;
108 * @defgroup DBusMessage DBusMessage
110 * @brief Message to be sent or received over a DBusConnection.
112 * A DBusMessage is the most basic unit of communication over a
113 * DBusConnection. A DBusConnection represents a stream of messages
114 * received from a remote application, and a stream of messages
115 * sent to a remote application.
121 * @typedef DBusMessage
123 * Opaque data type representing a message received from or to be
124 * sent to another application.
128 * Constructs a new message. Returns #NULL if memory
129 * can't be allocated for the message.
131 * @return a new DBusMessage, free with dbus_message_unref()
132 * @see dbus_message_unref()
135 dbus_message_new (void)
137 DBusMessage *message;
139 message = dbus_new0 (DBusMessage, 1);
143 message->refcount = 1;
145 if (!_dbus_string_init (&message->header, _DBUS_MAX_MESSAGE_LENGTH))
151 if (!_dbus_string_init (&message->body, _DBUS_MAX_MESSAGE_LENGTH))
153 _dbus_string_free (&message->header);
158 /* We need to decide what a message contains. ;-) */
159 /* (not bothering to check failure of these appends) */
160 _dbus_string_append (&message->header, "H");
161 _dbus_string_append_byte (&message->header, '\0');
162 _dbus_string_append (&message->body, "Body");
163 _dbus_string_append_byte (&message->body, '\0');
170 * Increments the reference count of a DBusMessage.
172 * @param message The message
173 * @see dbus_message_unref
176 dbus_message_ref (DBusMessage *message)
178 message->refcount += 1;
182 * Decrements the reference count of a DBusMessage.
184 * @param message The message
185 * @see dbus_message_ref
188 dbus_message_unref (DBusMessage *message)
190 _dbus_assert (message != NULL);
191 _dbus_assert (message->refcount > 0);
193 message->refcount -= 1;
194 if (message->refcount == 0)
196 _dbus_string_free (&message->header);
197 _dbus_string_free (&message->body);
204 * Gets the name of a message.
205 * @param message the message
206 * @returns the message name (should not be freed)
209 dbus_message_get_name (DBusMessage *message)
219 * @addtogroup DBusMessageInternals
224 * @typedef DBusMessageLoader
226 * The DBusMessageLoader object encapsulates the process of converting
227 * a byte stream into a series of DBusMessage. It buffers the incoming
228 * bytes as efficiently as possible, and generates a queue of
229 * messages. DBusMessageLoader is typically used as part of a
230 * DBusTransport implementation. The DBusTransport then hands off
231 * the loaded messages to a DBusConnection, making the messages
232 * visible to the application.
237 * Implementation details of DBusMessageLoader.
238 * All members are private.
240 struct DBusMessageLoader
242 int refcount; /**< Reference count. */
244 DBusString data; /**< Buffered data */
246 DBusList *messages; /**< Complete messages. */
248 unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
252 * The initial buffer size of the message loader.
254 * @todo this should be based on min header size plus some average
255 * body size, or something. Or rather, the min header size only, if we
256 * want to try to read only the header, store that in a DBusMessage,
257 * then read only the body and store that, etc., depends on
258 * how we optimize _dbus_message_loader_get_buffer() and what
259 * the exact message format is.
261 #define INITIAL_LOADER_DATA_LEN 32
264 * Creates a new message loader. Returns #NULL if memory can't
267 * @returns new loader, or #NULL.
270 _dbus_message_loader_new (void)
272 DBusMessageLoader *loader;
274 loader = dbus_new0 (DBusMessageLoader, 1);
278 loader->refcount = 1;
280 if (!_dbus_string_init (&loader->data, _DBUS_INT_MAX))
286 /* preallocate the buffer for speed, ignore failure */
287 (void) _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
293 * Increments the reference count of the loader.
295 * @param loader the loader.
298 _dbus_message_loader_ref (DBusMessageLoader *loader)
300 loader->refcount += 1;
304 * Decrements the reference count of the loader and finalizes the
305 * loader when the count reaches zero.
307 * @param loader the loader.
310 _dbus_message_loader_unref (DBusMessageLoader *loader)
312 loader->refcount -= 1;
313 if (loader->refcount == 0)
315 _dbus_list_foreach (&loader->messages,
316 (DBusForeachFunction) dbus_message_unref,
318 _dbus_list_clear (&loader->messages);
319 _dbus_string_free (&loader->data);
325 * Gets the buffer to use for reading data from the network. Network
326 * data is read directly into an allocated buffer, which is then used
327 * in the DBusMessage, to avoid as many extra memcpy's as possible.
328 * The buffer must always be returned immediately using
329 * _dbus_message_loader_return_buffer(), even if no bytes are
332 * @todo this function can be a lot more clever. For example
333 * it can probably always return a buffer size to read exactly
334 * the body of the next message, thus avoiding any memory wastage
337 * @param loader the message loader.
338 * @param buffer the buffer
341 _dbus_message_loader_get_buffer (DBusMessageLoader *loader,
344 _dbus_assert (!loader->buffer_outstanding);
346 *buffer = &loader->data;
348 loader->buffer_outstanding = TRUE;
352 * Returns a buffer obtained from _dbus_message_loader_get_buffer(),
353 * indicating to the loader how many bytes of the buffer were filled
354 * in. This function must always be called, even if no bytes were
357 * @param loader the loader.
358 * @param buffer the buffer.
359 * @param bytes_read number of bytes that were read into the buffer.
362 _dbus_message_loader_return_buffer (DBusMessageLoader *loader,
366 _dbus_assert (loader->buffer_outstanding);
367 _dbus_assert (buffer == &loader->data);
369 /* FIXME fake implementation just creates a message for every 7
370 * bytes. The real implementation will pass ownership of
371 * loader->data bytes to new messages, to avoid memcpy. We can also
372 * smart-realloc loader->data to shrink it if it's too big, though
373 * _dbus_message_loader_get_buffer() could strategically arrange for
374 * that to usually not happen.
377 loader->buffer_outstanding = FALSE;
379 while (_dbus_string_get_length (&loader->data) >= 7)
381 DBusMessage *message;
383 message = dbus_message_new ();
385 break; /* ugh, postpone this I guess. */
387 _dbus_list_append (&loader->messages, message);
389 _dbus_string_delete (&loader->data,
392 _dbus_verbose ("Loaded message %p\n", message);
397 * Pops a loaded message (passing ownership of the message
398 * to the caller). Returns #NULL if no messages have been
401 * @param loader the loader.
402 * @returns the next message, or #NULL if none.
405 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
407 return _dbus_list_pop_first (&loader->messages);