2003-01-07 Anders Carlsson <andersca@codefactory.se>

* dbus/dbus-connection-internal.h:
	* dbus/dbus-connection.c: (_dbus_connection_new_for_transport),
	(_dbus_connection_get_next_client_serial),
	(dbus_connection_send_message):
	* dbus/dbus-internals.h:
	* dbus/dbus-marshal.c: (unpack_uint32), (dbus_unpack_int32),
	(dbus_pack_int32), (_dbus_marshal_double), (_dbus_marshal_int32),
	(_dbus_marshal_uint32), (_dbus_demarshal_double),
	(_dbus_demarshal_int32), (_dbus_demarshal_uint32),
	(_dbus_demarshal_string), (_dbus_marshal_get_field_end_pos),
	(_dbus_verbose_bytes), (_dbus_marshal_test):
	* dbus/dbus-marshal.h:
	* dbus/dbus-message-internal.h:
	* dbus/dbus-message.c: (_dbus_message_set_client_serial),
	(dbus_message_write_header), (_dbus_message_lock),
	(dbus_message_new), (dbus_message_ref), (dbus_message_unref),
	(dbus_message_get_name), (dbus_message_append_int32),
	(dbus_message_append_uint32), (dbus_message_append_double),
	(dbus_message_append_string), (dbus_message_append_byte_array),
	(dbus_message_get_fields_iter), (dbus_message_iter_ref),
	(dbus_message_iter_unref), (dbus_message_iter_has_next),
	(dbus_message_iter_next), (dbus_message_iter_get_field_type),
	(dbus_message_iter_get_string), (dbus_message_iter_get_int32),
	(dbus_message_iter_get_uint32), (dbus_message_iter_get_double),
	(decode_header_data), (_dbus_message_loader_return_buffer),
	(message_iter_test), (_dbus_message_test):
	* dbus/dbus-message.h:
	* dbus/dbus-protocol.h:
	* dbus/dbus-test.c: (main):
	* dbus/dbus-test.h:
	* glib/test-dbus-glib.c: (message_handler), (main):
	* test/echo-client.c: (main):
	* test/watch.c: (check_messages):
	Make messages sendable and receivable for real.
This commit is contained in:
Anders Carlsson 2003-01-07 20:18:23 +00:00
parent 49686ee969
commit 1b53cbcce3
15 changed files with 784 additions and 106 deletions

View file

@ -1,3 +1,40 @@
2003-01-07 Anders Carlsson <andersca@codefactory.se>
* dbus/dbus-connection-internal.h:
* dbus/dbus-connection.c: (_dbus_connection_new_for_transport),
(_dbus_connection_get_next_client_serial),
(dbus_connection_send_message):
* dbus/dbus-internals.h:
* dbus/dbus-marshal.c: (unpack_uint32), (dbus_unpack_int32),
(dbus_pack_int32), (_dbus_marshal_double), (_dbus_marshal_int32),
(_dbus_marshal_uint32), (_dbus_demarshal_double),
(_dbus_demarshal_int32), (_dbus_demarshal_uint32),
(_dbus_demarshal_string), (_dbus_marshal_get_field_end_pos),
(_dbus_verbose_bytes), (_dbus_marshal_test):
* dbus/dbus-marshal.h:
* dbus/dbus-message-internal.h:
* dbus/dbus-message.c: (_dbus_message_set_client_serial),
(dbus_message_write_header), (_dbus_message_lock),
(dbus_message_new), (dbus_message_ref), (dbus_message_unref),
(dbus_message_get_name), (dbus_message_append_int32),
(dbus_message_append_uint32), (dbus_message_append_double),
(dbus_message_append_string), (dbus_message_append_byte_array),
(dbus_message_get_fields_iter), (dbus_message_iter_ref),
(dbus_message_iter_unref), (dbus_message_iter_has_next),
(dbus_message_iter_next), (dbus_message_iter_get_field_type),
(dbus_message_iter_get_string), (dbus_message_iter_get_int32),
(dbus_message_iter_get_uint32), (dbus_message_iter_get_double),
(decode_header_data), (_dbus_message_loader_return_buffer),
(message_iter_test), (_dbus_message_test):
* dbus/dbus-message.h:
* dbus/dbus-protocol.h:
* dbus/dbus-test.c: (main):
* dbus/dbus-test.h:
* glib/test-dbus-glib.c: (message_handler), (main):
* test/echo-client.c: (main):
* test/watch.c: (check_messages):
Make messages sendable and receivable for real.
2003-01-07 Anders Carlsson <andersca@codefactory.se>
* dbus/dbus-marshal.c: (_dbus_marshal_double),

View file

@ -51,7 +51,6 @@ void _dbus_connection_remove_watch (DBusConnection *connect
DBusWatch *watch);
DBusConnection* _dbus_connection_new_for_transport (DBusTransport *transport);
void _dbus_connection_do_iteration (DBusConnection *connection,
unsigned int flags,
int timeout_milliseconds);

View file

@ -92,6 +92,8 @@ struct DBusConnection
int handlers_serial; /**< Increments when the handler table is changed. */
DBusDataSlot *data_slots; /**< Data slots */
int n_slots; /**< Slots allocated so far. */
int client_serial; /**< Client serial. Increments each time a message is sent */
};
static void _dbus_connection_free_data_slots (DBusConnection *connection);
@ -330,6 +332,7 @@ _dbus_connection_new_for_transport (DBusTransport *transport)
connection->data_slots = NULL;
connection->n_slots = 0;
connection->client_serial = 1;
_dbus_transport_ref (transport);
_dbus_transport_set_connection (transport, connection);
@ -350,6 +353,19 @@ _dbus_connection_new_for_transport (DBusTransport *transport)
return NULL;
}
static dbus_int32_t
_dbus_connection_get_next_client_serial (DBusConnection *connection)
{
int serial;
serial = connection->client_serial++;
if (connection->client_serial < 0)
connection->client_serial = 1;
return serial;
}
/**
* Used to notify a connection when a DBusMessageHandler is
* destroyed, so the connection can drop any reference
@ -580,7 +596,8 @@ dbus_connection_send_message (DBusConnection *connection,
_dbus_verbose ("Message %p added to outgoing queue, %d pending to send\n",
message, connection->n_outgoing);
_dbus_message_set_client_serial (message, _dbus_connection_get_next_client_serial (connection));
_dbus_message_lock (message);
if (connection->n_outgoing == 1)

View file

@ -72,6 +72,23 @@ do {
#define _DBUS_STRUCT_OFFSET(struct_type, member) \
((long) ((unsigned char*) &((struct_type*) 0)->member))
/* This alignment thing is from ORBit2 */
/* Align a value upward to a boundary, expressed as a number of bytes.
* E.g. align to an 8-byte boundary with argument of 8.
*/
/*
* (this + boundary - 1)
* &
* ~(boundary - 1)
*/
#define _DBUS_ALIGN_VALUE(this, boundary) \
(( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
#define _DBUS_ALIGN_ADDRESS(this, boundary) \
((void*)_DBUS_ALIGN_VALUE(this, boundary))
char* _dbus_strdup (const char *str);
#define _DBUS_INT_MIN (-_DBUS_INT_MAX - 1)

View file

@ -53,23 +53,6 @@
#define DBUS_UINT32_FROM_BE(val) (DBUS_UINT32_TO_BE (val))
/* This alignment thing is from ORBit2 */
/* Align a value upward to a boundary, expressed as a number of bytes.
* E.g. align to an 8-byte boundary with argument of 8.
*/
/*
* (this + boundary - 1)
* &
* ~(boundary - 1)
*/
#define DBUS_ALIGN_VALUE(this, boundary) \
(( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
#define DBUS_ALIGN_ADDRESS(this, boundary) \
((void*)DBUS_ALIGN_VALUE(this, boundary))
/* from ORBit */
static void
swap_bytes (unsigned char *data,
@ -93,7 +76,7 @@ static dbus_uint32_t
unpack_uint32 (int byte_order,
const unsigned char *data)
{
_dbus_assert (DBUS_ALIGN_ADDRESS (data, 4) == data);
_dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
if (byte_order == DBUS_LITTLE_ENDIAN)
return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
@ -101,11 +84,18 @@ unpack_uint32 (int byte_order,
return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
}
static dbus_int32_t
unpack_int32 (int byte_order,
const unsigned char *data)
/**
* Unpacks a 32 bit unsigned integer from a data pointer
*
* @param byte_order The byte order to use
* @param data the data pointer
* @returns the integer
*/
dbus_int32_t
dbus_unpack_int32 (int byte_order,
const unsigned char *data)
{
_dbus_assert (DBUS_ALIGN_ADDRESS (data, 4) == data);
_dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
if (byte_order == DBUS_LITTLE_ENDIAN)
return DBUS_INT32_FROM_LE (*(dbus_int32_t*)data);
@ -124,6 +114,26 @@ unpack_int32 (int byte_order,
* @{
*/
/**
* Packs a 32 bit unsigned integer into a data pointer.
*
* @param value the value
* @param byte_order the byte order to use
* @param data the data pointer
*/
void
dbus_pack_int32 (dbus_int32_t value,
int byte_order,
unsigned char *data)
{
_dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
if ((byte_order) == DBUS_LITTLE_ENDIAN)
*((dbus_int32_t*)(data)) = DBUS_INT32_TO_LE (value);
else
*((dbus_int32_t*)(data)) = DBUS_INT32_TO_BE (value);
}
/**
* Marshals a double value.
*
@ -137,6 +147,11 @@ _dbus_marshal_double (DBusString *str,
int byte_order,
double value)
{
if (!_dbus_string_set_length (str,
_DBUS_ALIGN_VALUE (_dbus_string_get_length (str),
sizeof (double))))
return FALSE;
if (byte_order != DBUS_COMPILER_BYTE_ORDER)
swap_bytes ((unsigned char *)&value, sizeof (double));
@ -157,7 +172,7 @@ _dbus_marshal_int32 (DBusString *str,
dbus_int32_t value)
{
if (!_dbus_string_set_length (str,
DBUS_ALIGN_VALUE (_dbus_string_get_length (str),
_DBUS_ALIGN_VALUE (_dbus_string_get_length (str),
sizeof (dbus_int32_t))))
return FALSE;
@ -181,7 +196,7 @@ _dbus_marshal_uint32 (DBusString *str,
dbus_uint32_t value)
{
if (!_dbus_string_set_length (str,
DBUS_ALIGN_VALUE (_dbus_string_get_length (str),
_DBUS_ALIGN_VALUE (_dbus_string_get_length (str),
sizeof (dbus_uint32_t))))
return FALSE;
@ -269,8 +284,8 @@ _dbus_demarshal_double (DBusString *str,
double retval;
const char *buffer;
pos = DBUS_ALIGN_VALUE (pos, sizeof (double));
pos = _DBUS_ALIGN_VALUE (pos, sizeof (double));
_dbus_string_get_const_data_len (str, &buffer, pos, sizeof (double));
retval = *(double *)buffer;
@ -301,14 +316,14 @@ _dbus_demarshal_int32 (DBusString *str,
{
const char *buffer;
pos = DBUS_ALIGN_VALUE (pos, sizeof (dbus_int32_t));
pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_int32_t));
_dbus_string_get_const_data_len (str, &buffer, pos, sizeof (dbus_int32_t));
if (new_pos)
*new_pos = pos + sizeof (dbus_int32_t);
return unpack_int32 (byte_order, buffer);
return dbus_unpack_int32 (byte_order, buffer);
}
/**
@ -328,7 +343,7 @@ _dbus_demarshal_uint32 (DBusString *str,
{
const char *buffer;
pos = DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
_dbus_string_get_const_data_len (str, &buffer, pos, sizeof (dbus_uint32_t));
@ -368,7 +383,7 @@ _dbus_demarshal_string (DBusString *str,
if (!retval)
return NULL;
_dbus_string_get_const_data_len (str, &data, pos, 3);
_dbus_string_get_const_data_len (str, &data, pos, len);
if (!data)
return NULL;
@ -381,6 +396,86 @@ _dbus_demarshal_string (DBusString *str,
return retval;
}
/**
* Returns the position right after the end position
* end position of a field
*
* @param str a string
* @param byte_order the byte order to use
* @param pos the pos where the field starts
* @param end_pos pointer where the position right
* after the end position will follow
* @returns TRUE if more data exists after the field
*/
dbus_bool_t
_dbus_marshal_get_field_end_pos (DBusString *str,
int byte_order,
int pos,
int *end_pos)
{
const char *data;
if (pos >= _dbus_string_get_length (str))
return FALSE;
_dbus_string_get_const_data_len (str, &data, pos, 1);
switch (*data)
{
case DBUS_TYPE_INVALID:
return FALSE;
break;
case DBUS_TYPE_INT32:
*end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_int32_t)) + sizeof (dbus_int32_t);
break;
case DBUS_TYPE_UINT32:
*end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_uint32_t)) + sizeof (dbus_uint32_t);
break;
case DBUS_TYPE_DOUBLE:
*end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (double)) + sizeof (double);
break;
case DBUS_TYPE_STRING:
{
int len, new_pos;
/* Demarshal the length */
len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
*end_pos = new_pos + len + 1;
break;
}
case DBUS_TYPE_BYTE_ARRAY:
{
int len, new_pos;
/* Demarshal the length */
len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
*end_pos = new_pos + len;
break;
}
default:
_dbus_warn ("Unknown message field type %d\n", *data);
return FALSE;
}
if (*end_pos >= _dbus_string_get_length (str))
return FALSE;
return TRUE;
}
/**
* If in verbose mode, print a block of binary data.
*
@ -397,7 +492,7 @@ _dbus_verbose_bytes (const unsigned char *data,
const unsigned char *aligned;
/* Print blanks on first row if appropriate */
aligned = DBUS_ALIGN_ADDRESS (data, 4);
aligned = _DBUS_ALIGN_ADDRESS (data, 4);
if (aligned > data)
aligned -= 4;
_dbus_assert (aligned <= data);
@ -416,7 +511,7 @@ _dbus_verbose_bytes (const unsigned char *data,
i = 0;
while (i < len)
{
if (DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
{
_dbus_verbose ("%5d\t%p: ",
i, &data[i]);
@ -431,7 +526,7 @@ _dbus_verbose_bytes (const unsigned char *data,
++i;
if (DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
{
if (i > 3)
_dbus_verbose ("big: %d little: %d",
@ -486,7 +581,6 @@ _dbus_marshal_test (void)
_dbus_assert_not_reached ("could not marshal double value");
_dbus_assert (_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14);
if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14))
_dbus_assert_not_reached ("could not marshal double value");
_dbus_assert (_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14);

View file

@ -39,6 +39,13 @@
#define DBUS_COMPILER_BYTE_ORDER DBUS_LITTLE_ENDIAN
#endif
void dbus_pack_int32 (dbus_int32_t value,
int byte_order,
unsigned char *data);
dbus_int32_t dbus_unpack_int32 (int byte_order,
const unsigned char *data);
dbus_bool_t _dbus_marshal_double (DBusString *str,
int byte_order,
double value);
@ -73,7 +80,10 @@ char * _dbus_demarshal_string (DBusString *str,
int pos,
int *new_pos);
dbus_bool_t _dbus_marshal_get_field_end_pos (DBusString *str,
int byte_order,
int pos,
int *end_pos);

View file

@ -29,12 +29,14 @@ DBUS_BEGIN_DECLS;
typedef struct DBusMessageLoader DBusMessageLoader;
void _dbus_message_get_network_data (DBusMessage *message,
const DBusString **header,
const DBusString **body);
void _dbus_message_get_network_data (DBusMessage *message,
const DBusString **header,
const DBusString **body);
void _dbus_message_lock (DBusMessage *message);
void _dbus_message_lock (DBusMessage *message);
void _dbus_message_set_client_serial (DBusMessage *message,
dbus_int32_t client_serial);
DBusMessageLoader* _dbus_message_loader_new (void);
void _dbus_message_loader_ref (DBusMessageLoader *loader);

View file

@ -2,6 +2,7 @@
/* dbus-message.c DBusMessage object
*
* Copyright (C) 2002 Red Hat Inc.
* Copyright (C) 2002, 2003 CodeFactory AB
*
* Licensed under the Academic Free License version 1.2
*
@ -64,9 +65,26 @@ struct DBusMessage
DBusString body; /**< Body network data. */
char byte_order; /**< Message byte order. */
char *name; /**< Message name. */
char *service; /**< Message destination service. */
dbus_int32_t client_serial; /**< Client serial or -1 if not set */
dbus_int32_t reply_serial; /**< Reply serial or -1 if not set */
unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
};
struct DBusMessageIter
{
int refcount; /**< Reference count */
int pos; /**< Current position in the string */
DBusMessage *message; /**< Message used */
};
/**
* Gets the data to be sent over the network for this message.
* The header and then the body should be written out.
@ -88,6 +106,69 @@ _dbus_message_get_network_data (DBusMessage *message,
*body = &message->body;
}
/**
* Sets the client serial of a message.
* This can only be done once on a message.
*
* @param message the message
* @param client_serial the client serial
*/
void
_dbus_message_set_client_serial (DBusMessage *message,
dbus_int32_t client_serial)
{
_dbus_assert (message->client_serial == -1);
message->client_serial = client_serial;
}
static void
dbus_message_write_header (DBusMessage *message)
{
char *header;
_dbus_assert (message->client_serial != -1);
_dbus_string_append_byte (&message->header, DBUS_COMPILER_BYTE_ORDER);
_dbus_string_append_len (&message->header, "\0\0\0", 3);
/* We just lengthen the string here and pack in the real length later */
_dbus_string_lengthen (&message->header, 4);
_dbus_marshal_int32 (&message->header, DBUS_COMPILER_BYTE_ORDER, _dbus_string_get_length (&message->body));
/* Marshal client serial */
_dbus_marshal_int32 (&message->header, DBUS_COMPILER_BYTE_ORDER, message->client_serial);
/* Marshal message service */
if (message->service)
{
_dbus_string_append_len (&message->header, DBUS_HEADER_FIELD_SERVICE, 4);
_dbus_string_append_byte (&message->header, DBUS_TYPE_STRING);
_dbus_marshal_string (&message->header, DBUS_COMPILER_BYTE_ORDER, message->service);
}
/* Marshal message name */
_dbus_string_append_len (&message->header, DBUS_HEADER_FIELD_NAME, 4);
_dbus_string_append_byte (&message->header, DBUS_TYPE_STRING);
_dbus_marshal_string (&message->header, DBUS_COMPILER_BYTE_ORDER, message->name);
/* Marshal reply serial */
if (message->reply_serial != -1)
{
_dbus_string_append_len (&message->header, DBUS_HEADER_FIELD_REPLY, 4);
_dbus_string_append_byte (&message->header, DBUS_TYPE_INT32);
_dbus_marshal_int32 (&message->header, DBUS_COMPILER_BYTE_ORDER, message->reply_serial);
}
/* Fill in the length */
_dbus_string_get_data_len (&message->header, &header, 4, 4);
dbus_pack_int32 (_dbus_string_get_length (&message->header), DBUS_COMPILER_BYTE_ORDER, header);
}
/**
* Locks a message. Allows checking that applications don't keep a
* reference to a message in the outgoing queue and change it
@ -98,8 +179,11 @@ _dbus_message_get_network_data (DBusMessage *message,
* @param message the message to lock.
*/
void
_dbus_message_lock (DBusMessage *message)
_dbus_message_lock (DBusMessage *message)
{
if (!message->locked)
dbus_message_write_header (message);
message->locked = TRUE;
}
@ -128,12 +212,16 @@ _dbus_message_lock (DBusMessage *message)
/**
* Constructs a new message. Returns #NULL if memory
* can't be allocated for the message.
*
* @return a new DBusMessage, free with dbus_message_unref()
*
* @param service service that the message should be sent to
* should be sent to
* @param name name of the message
* @returns a new DBusMessage, free with dbus_message_unref()
* @see dbus_message_unref()
*/
DBusMessage*
dbus_message_new (void)
dbus_message_new (const char *service,
const char *name)
{
DBusMessage *message;
@ -142,7 +230,14 @@ dbus_message_new (void)
return NULL;
message->refcount = 1;
message->byte_order = DBUS_COMPILER_BYTE_ORDER;
message->service = _dbus_strdup (service);
message->name = _dbus_strdup (name);
message->client_serial = -1;
message->reply_serial = -1;
if (!_dbus_string_init (&message->header, _DBUS_MAX_MESSAGE_LENGTH))
{
dbus_free (message);
@ -156,13 +251,6 @@ dbus_message_new (void)
return NULL;
}
/* We need to decide what a message contains. ;-) */
/* (not bothering to check failure of these appends) */
_dbus_string_append (&message->header, "H");
_dbus_string_append_byte (&message->header, '\0');
_dbus_string_append (&message->body, "Body");
_dbus_string_append_byte (&message->body, '\0');
return message;
}
@ -176,6 +264,8 @@ dbus_message_new (void)
void
dbus_message_ref (DBusMessage *message)
{
_dbus_assert (message->refcount > 0);
message->refcount += 1;
}
@ -188,7 +278,6 @@ dbus_message_ref (DBusMessage *message)
void
dbus_message_unref (DBusMessage *message)
{
_dbus_assert (message != NULL);
_dbus_assert (message->refcount > 0);
message->refcount -= 1;
@ -197,6 +286,7 @@ dbus_message_unref (DBusMessage *message)
_dbus_string_free (&message->header);
_dbus_string_free (&message->body);
dbus_free (message->name);
dbus_free (message);
}
}
@ -210,9 +300,7 @@ dbus_message_unref (DBusMessage *message)
const char*
dbus_message_get_name (DBusMessage *message)
{
/* FIXME */
return NULL;
return message->name;
}
/**
@ -226,7 +314,6 @@ dbus_bool_t
dbus_message_append_int32 (DBusMessage *message,
dbus_int32_t value)
{
_dbus_assert (message != NULL);
_dbus_assert (!message->locked);
if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_INT32))
@ -250,7 +337,6 @@ dbus_bool_t
dbus_message_append_uint32 (DBusMessage *message,
dbus_uint32_t value)
{
_dbus_assert (message != NULL);
_dbus_assert (!message->locked);
if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_UINT32))
@ -274,10 +360,9 @@ dbus_bool_t
dbus_message_append_double (DBusMessage *message,
double value)
{
_dbus_assert (message != NULL);
_dbus_assert (!message->locked);
if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_INT32))
if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DOUBLE))
{
_dbus_string_shorten (&message->body, 1);
return FALSE;
@ -298,11 +383,9 @@ dbus_bool_t
dbus_message_append_string (DBusMessage *message,
const char *value)
{
_dbus_assert (message != NULL);
_dbus_assert (!message->locked);
_dbus_assert (value != NULL);
if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_UTF8_STRING))
if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_STRING))
{
_dbus_string_shorten (&message->body, 1);
return FALSE;
@ -325,9 +408,7 @@ dbus_message_append_byte_array (DBusMessage *message,
unsigned const char *value,
int len)
{
_dbus_assert (message != NULL);
_dbus_assert (!message->locked);
_dbus_assert (value != NULL);
if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_BYTE_ARRAY))
{
@ -339,6 +420,198 @@ dbus_message_append_byte_array (DBusMessage *message,
DBUS_COMPILER_BYTE_ORDER, value, len);
}
/**
* Returns a DBusMessageIter representing the fields of the
* message passed in.
*
* @param message the message
* @returns a new iter.
*/
DBusMessageIter *
dbus_message_get_fields_iter (DBusMessage *message)
{
DBusMessageIter *iter;
iter = dbus_new (DBusMessageIter, 1);
dbus_message_ref (message);
iter->refcount = 1;
iter->message = message;
iter->pos = 0;
return iter;
}
/**
* Increments the reference count of a DBusMessageIter.
*
* @param iter the message iter
* @see dbus_message_iter_unref
*/
void
dbus_message_iter_ref (DBusMessageIter *iter)
{
_dbus_assert (iter->refcount > 0);
iter->refcount += 1;
}
/**
* Decrements the reference count of a DBusMessageIter.
*
* @param iter The message iter
* @see dbus_message_iter_ref
*/
void
dbus_message_iter_unref (DBusMessageIter *iter)
{
_dbus_assert (iter->refcount > 0);
iter->refcount -= 1;
if (iter->refcount == 0)
{
dbus_message_unref (iter->message);
dbus_free (iter);
}
}
/**
* Checks if an iterator has any more fields.
*
* @param iter the message iter
* @returns #TRUE if there are more fields
* following
*/
dbus_bool_t
dbus_message_iter_has_next (DBusMessageIter *iter)
{
int end_pos;
if (!_dbus_marshal_get_field_end_pos (&iter->message->body, iter->message->byte_order,
iter->pos, &end_pos))
return FALSE;
if (end_pos >= _dbus_string_get_length (&iter->message->body))
return FALSE;
return TRUE;
}
/**
* Moves the iterator to the next field.
*
* @param iter The message iter
* @returns #TRUE if the iterator was moved to the next field
*/
dbus_bool_t
dbus_message_iter_next (DBusMessageIter *iter)
{
int end_pos;
if (!_dbus_marshal_get_field_end_pos (&iter->message->body, iter->message->byte_order,
iter->pos, &end_pos))
return FALSE;
if (end_pos >= _dbus_string_get_length (&iter->message->body))
return FALSE;
iter->pos = end_pos;
return TRUE;
}
/**
* Returns the field type of the field that the
* message iterator points at.
*
* @param iter the message iter
* @returns the field type
*/
int
dbus_message_iter_get_field_type (DBusMessageIter *iter)
{
const char *data;
if (iter->pos >= _dbus_string_get_length (&iter->message->body))
return DBUS_TYPE_INVALID;
_dbus_string_get_const_data_len (&iter->message->body, &data, iter->pos, 1);
if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_STRING)
return *data;
return DBUS_TYPE_INVALID;
}
/**
* Returns the string value that an iterator may point to.
* Note that you need to check that the iterator points to
* a string value before using this function.
*
* @see dbus_message_iter_get_field_type
* @param iter the message iter
* @returns the string
*/
char *
dbus_message_iter_get_string (DBusMessageIter *iter)
{
_dbus_assert (dbus_message_iter_get_field_type (iter) == DBUS_TYPE_STRING);
return _dbus_demarshal_string (&iter->message->body, iter->message->byte_order,
iter->pos + 1, NULL);
}
/**
* Returns the 32 bit signed integer value that an iterator may point to.
* Note that you need to check that the iterator points to
* a string value before using this function.
*
* @see dbus_message_iter_get_field_type
* @param iter the message iter
* @returns the integer
*/
int
dbus_message_iter_get_int32 (DBusMessageIter *iter)
{
return _dbus_demarshal_int32 (&iter->message->body, iter->message->byte_order,
iter->pos + 1, NULL);
}
/**
* Returns the 32 bit unsigned integer value that an iterator may point to.
* Note that you need to check that the iterator points to
* a string value before using this function.
*
* @see dbus_message_iter_get_field_type
* @param iter the message iter
* @returns the integer
*/
int
dbus_message_iter_get_uint32 (DBusMessageIter *iter)
{
return _dbus_demarshal_uint32 (&iter->message->body, iter->message->byte_order,
iter->pos + 1, NULL);
}
/**
* Returns the double value that an iterator may point to.
* Note that you need to check that the iterator points to
* a string value before using this function.
*
* @see dbus_message_iter_get_field_type
* @param iter the message iter
* @returns the double
*/
double
dbus_message_iter_get_double (DBusMessageIter *iter)
{
return _dbus_demarshal_double (&iter->message->body, iter->message->byte_order,
iter->pos + 1, NULL);
}
/** @} */
/**
@ -477,6 +750,65 @@ _dbus_message_loader_get_buffer (DBusMessageLoader *loader,
loader->buffer_outstanding = TRUE;
}
/**
* The smallest header size that can occur.
* (It won't be valid)
*/
#define DBUS_MINIMUM_HEADER_SIZE 16
static dbus_bool_t
decode_header_data (DBusString *data,
int header_len,
int byte_order,
dbus_int32_t *client_serial,
char **service,
char **name)
{
const char *field;
int pos, new_pos;
/* First demarshal the client serial */
*client_serial = _dbus_demarshal_int32 (data, byte_order, 12, &pos);
*service = NULL;
*name = NULL;
/* Now handle the fields */
while (pos < header_len)
{
_dbus_string_get_const_data_len (data, &field, pos, 4);
pos += 4;
if (pos > header_len)
return FALSE;
if (strncmp (field, DBUS_HEADER_FIELD_SERVICE, 4) == 0)
{
*service = _dbus_demarshal_string (data, byte_order, pos + 1, &new_pos);
}
else if (strncmp (field, DBUS_HEADER_FIELD_NAME, 4) == 0)
{
*name = _dbus_demarshal_string (data, byte_order, pos + 1, &new_pos);
}
else
{
_dbus_verbose ("Encountered an unknown header field: %c%c%c%c\n",
field[0], field[1], field[2], field[3]);
if (!_dbus_marshal_get_field_end_pos (data, byte_order, pos, &new_pos))
return FALSE;
}
if (new_pos > header_len)
return FALSE;
pos = new_pos;
}
return TRUE;
}
/**
* Returns a buffer obtained from _dbus_message_loader_get_buffer(),
* indicating to the loader how many bytes of the buffer were filled
@ -495,49 +827,67 @@ _dbus_message_loader_return_buffer (DBusMessageLoader *loader,
_dbus_assert (loader->buffer_outstanding);
_dbus_assert (buffer == &loader->data);
/* FIXME fake implementation just creates a message for every 7
* bytes. The real implementation will pass ownership of
* loader->data bytes to new messages, to avoid memcpy. We can also
* smart-realloc loader->data to shrink it if it's too big, though
* _dbus_message_loader_get_buffer() could strategically arrange for
* that to usually not happen.
*/
loader->buffer_outstanding = FALSE;
if (loader->corrupted)
return;
while (_dbus_string_get_length (&loader->data) >= 7)
while (_dbus_string_get_length (&loader->data) >= 16)
{
DBusMessage *message;
const char *d;
_dbus_string_get_const_data (&loader->data, &d);
if (d[0] != 'H' ||
d[1] != '\0' ||
d[2] != 'B' ||
d[3] != 'o' ||
d[4] != 'd' ||
d[5] != 'y' ||
d[6] != '\0')
{
_dbus_verbose_bytes (d,
_dbus_string_get_length (&loader->data));
loader->corrupted = TRUE;
return;
}
DBusMessage *message;
const char *header_data;
int byte_order, header_len, body_len;
message = dbus_message_new ();
if (message == NULL)
break; /* ugh, postpone this I guess. */
_dbus_string_get_const_data_len (&loader->data, &header_data, 0, 16);
byte_order = header_data[0];
_dbus_list_append (&loader->messages, message);
if (byte_order != DBUS_LITTLE_ENDIAN &&
byte_order != DBUS_BIG_ENDIAN)
{
loader->corrupted = TRUE;
return;
}
_dbus_string_delete (&loader->data,
0, 7);
_dbus_verbose ("Loaded message %p\n", message);
header_len = dbus_unpack_int32 (byte_order, header_data + 4);
body_len = dbus_unpack_int32 (byte_order, header_data + 8);
if (header_len + body_len > _DBUS_MAX_MESSAGE_LENGTH)
{
loader->corrupted = TRUE;
return;
}
if (_dbus_string_get_length (&loader->data) >= header_len + body_len)
{
dbus_int32_t client_serial;
char *service, *name;
if (!decode_header_data (&loader->data, header_len, byte_order,
&client_serial, &service, &name))
{
loader->corrupted = TRUE;
return;
}
message = dbus_message_new (service, name);
dbus_free (service);
dbus_free (name);
if (message == NULL)
break; /* ugh, postpone this I guess. */
_dbus_string_copy (&loader->data, header_len, &message->body, 0);
_dbus_message_set_client_serial (message, client_serial);
_dbus_list_append (&loader->messages, message);
_dbus_string_delete (&loader->data, 0, header_len + body_len);
_dbus_verbose ("Loaded message %p\n", message);
}
else
break;
}
}
@ -572,3 +922,129 @@ _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
}
/** @} */
#ifdef DBUS_BUILD_TESTS
#include "dbus-test.h"
#include <stdio.h>
static void
message_iter_test (DBusMessage *message)
{
DBusMessageIter *iter;
char *str;
iter = dbus_message_get_fields_iter (message);
/* String tests */
if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_STRING)
_dbus_assert_not_reached ("Field type isn't string");
str = dbus_message_iter_get_string (iter);
if (strcmp (str, "Test string") != 0)
_dbus_assert_not_reached ("Strings differ");
dbus_free (str);
if (!dbus_message_iter_next (iter))
_dbus_assert_not_reached ("Reached end of fields");
/* Signed integer tests */
if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_INT32)
_dbus_assert_not_reached ("Field type isn't int32");
if (dbus_message_iter_get_int32 (iter) != -0x12345678)
_dbus_assert_not_reached ("Signed integers differ");
if (!dbus_message_iter_next (iter))
_dbus_assert_not_reached ("Reached end of fields");
/* Unsigned integer tests */
if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_UINT32)
_dbus_assert_not_reached ("Field type isn't int32");
if (dbus_message_iter_get_int32 (iter) != 0xedd1e)
_dbus_assert_not_reached ("Unsigned integers differ");
if (!dbus_message_iter_next (iter))
_dbus_assert_not_reached ("Reached end of fields");
/* Double tests */
if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_DOUBLE)
_dbus_assert_not_reached ("Field type isn't double");
if (dbus_message_iter_get_double (iter) != 3.14159)
_dbus_assert_not_reached ("Doubles differ");
if (dbus_message_iter_next (iter))
_dbus_assert_not_reached ("Didn't reach end of fields");
dbus_message_iter_unref (iter);
}
/**
* @ingroup DBusMessageInternals
* Unit test for DBusMessage.
*
* @returns #TRUE on success.
*/
dbus_bool_t
_dbus_message_test (void)
{
DBusMessage *message;
DBusMessageLoader *loader;
int i;
const char *data;
message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
message->client_serial = 1;
dbus_message_append_string (message, "Test string");
dbus_message_append_int32 (message, -0x12345678);
dbus_message_append_uint32 (message, 0xedd1e);
dbus_message_append_double (message, 3.14159);
message_iter_test (message);
/* Message loader test */
_dbus_message_lock (message);
loader = _dbus_message_loader_new ();
/* Write the header data one byte at a time */
_dbus_string_get_const_data (&message->header, &data);
for (i = 0; i < _dbus_string_get_length (&message->header); i++)
{
DBusString *buffer;
_dbus_message_loader_get_buffer (loader, &buffer);
_dbus_string_append_byte (buffer, data[i]);
_dbus_message_loader_return_buffer (loader, buffer, 1);
}
/* Write the body data one byte at a time */
_dbus_string_get_const_data (&message->body, &data);
for (i = 0; i < _dbus_string_get_length (&message->body); i++)
{
DBusString *buffer;
_dbus_message_loader_get_buffer (loader, &buffer);
_dbus_string_append_byte (buffer, data[i]);
_dbus_message_loader_return_buffer (loader, buffer, 1);
}
dbus_message_unref (message);
/* Now pop back the message */
if (_dbus_message_loader_get_is_corrupted (loader))
_dbus_assert_not_reached ("message loader corrupted");
message = _dbus_message_loader_pop_message (loader);
if (!message)
_dbus_assert_not_reached ("received a NULL message");
message_iter_test (message);
dbus_message_unref (message);
_dbus_message_loader_unref (loader);
return TRUE;
}
#endif /* DBUS_BUILD_TESTS */

View file

@ -33,8 +33,10 @@
DBUS_BEGIN_DECLS;
typedef struct DBusMessage DBusMessage;
typedef struct DBusMessageIter DBusMessageIter;
DBusMessage* dbus_message_new (void);
DBusMessage* dbus_message_new (const char *service,
const char *name);
void dbus_message_ref (DBusMessage *message);
void dbus_message_unref (DBusMessage *message);
@ -53,6 +55,20 @@ dbus_bool_t dbus_message_append_byte_array (DBusMessage *message,
unsigned const char *value,
int len);
DBusMessageIter *dbus_message_get_fields_iter (DBusMessage *message);
void dbus_message_iter_ref (DBusMessageIter *iter);
void dbus_message_iter_unref (DBusMessageIter *iter);
dbus_bool_t dbus_message_iter_has_next (DBusMessageIter *iter);
dbus_bool_t dbus_message_iter_next (DBusMessageIter *iter);
int dbus_message_iter_get_field_type (DBusMessageIter *iter);
int dbus_message_iter_get_int32 (DBusMessageIter *iter);
int dbus_message_iter_get_uint32 (DBusMessageIter *iter);
double dbus_message_iter_get_double (DBusMessageIter *iter);
char * dbus_message_iter_get_string (DBusMessageIter *iter);
DBUS_END_DECLS;

View file

@ -45,8 +45,13 @@ extern "C" {
#define DBUS_TYPE_UINT32_ARRAY 5
#define DBUS_TYPE_DOUBLE_ARRAY 6
#define DBUS_TYPE_BYTE_ARRAY 7
#define DBUS_TYPE_UTF8_STRING 8
#define DBUS_TYPE_STRING 8
/* Header fields */
#define DBUS_HEADER_FIELD_NAME "name"
#define DBUS_HEADER_FIELD_SERVICE "srvc"
#define DBUS_HEADER_FIELD_REPLY "rply"
#ifdef __cplusplus
}
#endif

View file

@ -44,6 +44,10 @@ main (int argc,
printf ("%s: running marshalling tests\n", argv[0]);
if (!_dbus_marshal_test ())
die ("marshalling");
printf ("%s: running message tests\n", argv[0]);
if (!_dbus_message_test ())
die ("messages");
printf ("%s: running memory pool tests\n", argv[0]);
if (!_dbus_mem_pool_test ())

View file

@ -31,5 +31,6 @@ dbus_bool_t _dbus_list_test (void);
dbus_bool_t _dbus_marshal_test (void);
dbus_bool_t _dbus_mem_pool_test (void);
dbus_bool_t _dbus_string_test (void);
dbus_bool_t _dbus_message_test (void);
#endif /* DBUS_TEST_H */

View file

@ -10,7 +10,7 @@ message_handler (DBusConnection *connection,
static int count = 0;
DBusMessage *reply;
reply = dbus_message_new ();
reply = dbus_message_new ("org.freedesktop.DBus.Test", "org.freedesktop.DBus.Test");
dbus_connection_send_message (connection,
reply,
NULL);
@ -47,7 +47,7 @@ main (int argc, char **argv)
g_source_attach (source, NULL);
g_source_set_callback (source, (GSourceFunc)message_handler, NULL, NULL);
message = dbus_message_new ();
message = dbus_message_new ("org.freedesktop.DBus.Test", "org.freedesktop.DBus.Test");
dbus_connection_send_message (connection,
message,
NULL);

View file

@ -27,7 +27,7 @@ main (int argc,
setup_connection (connection);
/* Send a message to get things going */
message = dbus_message_new ();
message = dbus_message_new ("org.freedesktop.DBus.Test", "org.freedesktop.DBus.Test");
dbus_connection_send_message (connection,
message,
NULL);

View file

@ -148,7 +148,7 @@ check_messages (void)
printf ("Received message %d, sending reply\n", count);
reply = dbus_message_new ();
reply = dbus_message_new ("org.freedesktop.DBus.Test", "org.freedesktop.DBus.Test");
dbus_connection_send_message (connection,
reply,
NULL);