summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--dbus/dbus-bus.c16
-rw-r--r--dbus/dbus-connection.c6
-rw-r--r--dbus/dbus-message-builder.c8
-rw-r--r--dbus/dbus-message.c174
-rw-r--r--dbus/dbus-message.h16
-rw-r--r--dbus/dbus-object-registry.c85
-rw-r--r--dbus/dbus-object.c5
-rw-r--r--dbus/dbus-protocol.h1
-rw-r--r--doc/dbus-specification.sgml58
-rw-r--r--test/data/invalid-messages/bad-endian.message2
-rw-r--r--test/data/valid-messages/simplest-manual.message2
12 files changed, 309 insertions, 73 deletions
diff --git a/ChangeLog b/ChangeLog
index e7daf2bc..2e961823 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
2003-08-01 Havoc Pennington <hp@pobox.com>
+ * dbus/dbus-object-registry.c (_dbus_object_registry_handle_and_unlock):
+ implement
+
+ * dbus/dbus-message.c (dbus_message_get_type): new function
+
+ * doc/dbus-specification.sgml: add "type" byte to messages
+
+2003-08-01 Havoc Pennington <hp@pobox.com>
+
* dbus/dbus-protocol.h (DBUS_MESSAGE_TYPE_*): introduce
a message type enum to distinguish kinds of message
(DBUS_HEADER_FLAG_NO_REPLY_EXPECTED): flag for a message
diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c
index 6ab1eccc..214978da 100644
--- a/dbus/dbus-bus.c
+++ b/dbus/dbus-bus.c
@@ -398,8 +398,8 @@ dbus_bus_register (DBusConnection *connection,
return TRUE;
}
- message = dbus_message_new (DBUS_MESSAGE_HELLO,
- DBUS_SERVICE_DBUS);
+ message = dbus_message_new_method_call (DBUS_MESSAGE_HELLO,
+ DBUS_SERVICE_DBUS);
if (!message)
@@ -516,8 +516,8 @@ dbus_bus_acquire_service (DBusConnection *connection,
_dbus_return_val_if_fail (service_name != NULL, 0);
_dbus_return_val_if_error_is_set (error, 0);
- message = dbus_message_new (DBUS_MESSAGE_ACQUIRE_SERVICE,
- DBUS_SERVICE_DBUS);
+ message = dbus_message_new_method_call (DBUS_MESSAGE_ACQUIRE_SERVICE,
+ DBUS_SERVICE_DBUS);
if (message == NULL)
@@ -590,8 +590,8 @@ dbus_bus_service_exists (DBusConnection *connection,
_dbus_return_val_if_fail (service_name != NULL, FALSE);
_dbus_return_val_if_error_is_set (error, FALSE);
- message = dbus_message_new (DBUS_MESSAGE_SERVICE_EXISTS,
- DBUS_SERVICE_DBUS);
+ message = dbus_message_new_method_call (DBUS_MESSAGE_SERVICE_EXISTS,
+ DBUS_SERVICE_DBUS);
if (message == NULL)
{
_DBUS_SET_OOM (error);
@@ -652,8 +652,8 @@ dbus_bus_activate_service (DBusConnection *connection,
DBusMessage *msg;
DBusMessage *reply;
- msg = dbus_message_new (DBUS_MESSAGE_ACTIVATE_SERVICE,
- DBUS_SERVICE_DBUS);
+ msg = dbus_message_new_method_call (DBUS_MESSAGE_ACTIVATE_SERVICE,
+ DBUS_SERVICE_DBUS);
if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, service_name,
DBUS_TYPE_UINT32, flags, DBUS_TYPE_INVALID))
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
index 4b72d600..ced50bd1 100644
--- a/dbus/dbus-connection.c
+++ b/dbus/dbus-connection.c
@@ -722,7 +722,7 @@ _dbus_connection_new_for_transport (DBusTransport *transport)
if (io_path_cond == NULL)
goto error;
- disconnect_message = dbus_message_new (DBUS_MESSAGE_LOCAL_DISCONNECT, NULL);
+ disconnect_message = dbus_message_new_signal (DBUS_MESSAGE_LOCAL_DISCONNECT);
if (disconnect_message == NULL)
goto error;
@@ -1615,8 +1615,8 @@ dbus_connection_send_with_reply (DBusConnection *connection,
dbus_message_handler_ref (reply_handler);
- reply = dbus_message_new_error_reply (message, DBUS_ERROR_NO_REPLY,
- "No reply within specified time");
+ reply = dbus_message_new_error (message, DBUS_ERROR_NO_REPLY,
+ "No reply within specified time");
if (!reply)
{
CONNECTION_UNLOCK (connection);
diff --git a/dbus/dbus-message-builder.c b/dbus/dbus-message-builder.c
index 390dda75..fc85fc32 100644
--- a/dbus/dbus-message-builder.c
+++ b/dbus/dbus-message-builder.c
@@ -393,8 +393,14 @@ _dbus_message_data_load (DBusString *dest,
goto parse_failed;
}
+ if (!_dbus_string_append_byte (dest, DBUS_MESSAGE_TYPE_METHOD_CALL))
+ {
+ _dbus_warn ("could not append message type\n");
+ goto parse_failed;
+ }
+
i = 0;
- while (i < 3)
+ while (i < 2)
{
if (!_dbus_string_append_byte (dest, '\0'))
{
diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c
index 52226603..c39ca3b4 100644
--- a/dbus/dbus-message.c
+++ b/dbus/dbus-message.c
@@ -73,6 +73,11 @@ typedef struct
*/
} HeaderField;
+#define BYTE_ORDER_OFFSET 0
+#define TYPE_OFFSET 1
+#define FLAGS_OFFSET 2
+#define VERSION_OFFSET 3
+
/**
* @brief Internals of DBusMessage
*
@@ -803,6 +808,7 @@ _dbus_message_remove_size_counter (DBusMessage *message,
static dbus_bool_t
dbus_message_create_header (DBusMessage *message,
+ int type,
const char *name,
const char *service)
{
@@ -811,6 +817,9 @@ dbus_message_create_header (DBusMessage *message,
if (!_dbus_string_append_byte (&message->header, message->byte_order))
return FALSE;
+ if (!_dbus_string_append_byte (&message->header, type))
+ return FALSE;
+
flags = 0;
if (!_dbus_string_append_byte (&message->header, flags))
return FALSE;
@@ -818,9 +827,6 @@ dbus_message_create_header (DBusMessage *message,
if (!_dbus_string_append_byte (&message->header, DBUS_MAJOR_PROTOCOL_VERSION))
return FALSE;
- if (!_dbus_string_append_byte (&message->header, 0))
- return FALSE;
-
message->header_fields[FIELD_HEADER_LENGTH].offset = 4;
if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
return FALSE;
@@ -944,10 +950,11 @@ dbus_message_new_empty_header (void)
/**
- * Constructs a new message. Returns #NULL if memory can't be
- * allocated for the message. The service may be #NULL in which case
- * no service is set; this is appropriate when using D-BUS in a
- * peer-to-peer context (no message bus).
+ * Constructs a new message to invoke a method on a remote
+ * object. Returns #NULL if memory can't be allocated for the
+ * message. The service may be #NULL in which case no service is set;
+ * this is appropriate when using D-BUS in a peer-to-peer context (no
+ * message bus).
*
* @param name name of the message
* @param destination_service service that the message should be sent to or #NULL
@@ -955,8 +962,8 @@ dbus_message_new_empty_header (void)
* @see dbus_message_unref()
*/
DBusMessage*
-dbus_message_new (const char *name,
- const char *destination_service)
+dbus_message_new_method_call (const char *name,
+ const char *destination_service)
{
DBusMessage *message;
@@ -966,7 +973,9 @@ dbus_message_new (const char *name,
if (message == NULL)
return NULL;
- if (!dbus_message_create_header (message, name, destination_service))
+ if (!dbus_message_create_header (message,
+ DBUS_MESSAGE_TYPE_METHOD_CALL,
+ name, destination_service))
{
dbus_message_unref (message);
return NULL;
@@ -976,37 +985,43 @@ dbus_message_new (const char *name,
}
/**
- * Constructs a message that is a reply to some other
- * message. Returns #NULL if memory can't be allocated
- * for the message.
+ * Constructs a message that is a reply to a method call. Returns
+ * #NULL if memory can't be allocated for the message.
*
- * @param original_message the message which the created
+ * @param method_call the message which the created
* message is a reply to.
* @returns a new DBusMessage, free with dbus_message_unref()
- * @see dbus_message_new(), dbus_message_unref()
+ * @see dbus_message_new_method_call(), dbus_message_unref()
*/
DBusMessage*
-dbus_message_new_reply (DBusMessage *original_message)
+dbus_message_new_method_return (DBusMessage *method_call)
{
DBusMessage *message;
const char *sender, *name;
- _dbus_return_val_if_fail (original_message != NULL, NULL);
+ _dbus_return_val_if_fail (method_call != NULL, NULL);
- sender = get_string_field (original_message,
+ sender = get_string_field (method_call,
FIELD_SENDER, NULL);
- name = get_string_field (original_message,
+ name = get_string_field (method_call,
FIELD_NAME, NULL);
/* sender is allowed to be null here in peer-to-peer case */
-
- message = dbus_message_new (name, sender);
-
+
+ message = dbus_message_new_empty_header ();
if (message == NULL)
return NULL;
+
+ if (!dbus_message_create_header (message,
+ DBUS_MESSAGE_TYPE_METHOD_RETURN,
+ name, sender))
+ {
+ dbus_message_unref (message);
+ return NULL;
+ }
if (!dbus_message_set_reply_serial (message,
- dbus_message_get_serial (original_message)))
+ dbus_message_get_serial (method_call)))
{
dbus_message_unref (message);
return NULL;
@@ -1016,40 +1031,78 @@ dbus_message_new_reply (DBusMessage *original_message)
}
/**
+ * Constructs a new message representing a signal emission. Returns
+ * #NULL if memory can't be allocated for the message. The name
+ * passed in is the name of the signal.
+ *
+ * @param name name of the signal
+ * @returns a new DBusMessage, free with dbus_message_unref()
+ * @see dbus_message_unref()
+ */
+DBusMessage*
+dbus_message_new_signal (const char *name)
+{
+ DBusMessage *message;
+
+ _dbus_return_val_if_fail (name != NULL, NULL);
+
+ message = dbus_message_new_empty_header ();
+ if (message == NULL)
+ return NULL;
+
+ if (!dbus_message_create_header (message,
+ DBUS_MESSAGE_TYPE_SIGNAL,
+ name, NULL))
+ {
+ dbus_message_unref (message);
+ return NULL;
+ }
+
+ return message;
+}
+
+/**
* Creates a new message that is an error reply to a certain message.
+ * Error replies are possible in response to method calls primarily.
*
- * @param original_message the original message
+ * @param reply_to the original message
* @param error_name the error name
* @param error_message the error message string or #NULL for none
* @returns a new error message
*/
DBusMessage*
-dbus_message_new_error_reply (DBusMessage *original_message,
- const char *error_name,
- const char *error_message)
+dbus_message_new_error (DBusMessage *reply_to,
+ const char *error_name,
+ const char *error_message)
{
DBusMessage *message;
const char *sender;
DBusMessageIter iter;
- _dbus_return_val_if_fail (original_message != NULL, NULL);
+ _dbus_return_val_if_fail (reply_to != NULL, NULL);
_dbus_return_val_if_fail (error_name != NULL, NULL);
- sender = get_string_field (original_message,
+ sender = get_string_field (reply_to,
FIELD_SENDER, NULL);
/* sender may be NULL for non-message-bus case or
* when the message bus is dealing with an unregistered
* connection.
*/
-
- message = dbus_message_new (error_name, sender);
-
+ message = dbus_message_new_empty_header ();
if (message == NULL)
return NULL;
+
+ if (!dbus_message_create_header (message,
+ DBUS_MESSAGE_TYPE_ERROR,
+ error_name, sender))
+ {
+ dbus_message_unref (message);
+ return NULL;
+ }
if (!dbus_message_set_reply_serial (message,
- dbus_message_get_serial (original_message)))
+ dbus_message_get_serial (reply_to)))
{
dbus_message_unref (message);
return NULL;
@@ -1201,6 +1254,28 @@ dbus_message_unref (DBusMessage *message)
}
/**
+ * Gets the type of a message. Types include
+ * DBUS_MESSAGE_TYPE_METHOD_CALL, DBUS_MESSAGE_TYPE_METHOD_RETURN,
+ * DBUS_MESSAGE_TYPE_ERROR, DBUS_MESSAGE_TYPE_SIGNAL, but other types
+ * are allowed and all code must silently ignore messages of unknown
+ * type. DBUS_MESSAGE_TYPE_INVALID will never be returned, however.
+ *
+ *
+ * @param message the message
+ * @returns the type of the message
+ */
+int
+dbus_message_get_type (DBusMessage *message)
+{
+ int type;
+
+ type = _dbus_string_get_byte (&message->header, 1);
+ _dbus_assert (type != DBUS_MESSAGE_TYPE_INVALID);
+
+ return type;
+}
+
+/**
* Gets the name of a message.
*
* @param message the message
@@ -3704,7 +3779,7 @@ dbus_message_set_is_error (DBusMessage *message,
_dbus_return_if_fail (message != NULL);
_dbus_return_if_fail (!message->locked);
- header = _dbus_string_get_data_len (&message->header, 1, 1);
+ header = _dbus_string_get_data_len (&message->header, FLAGS_OFFSET, 1);
if (is_error_reply)
*header |= DBUS_HEADER_FLAG_ERROR;
@@ -3726,7 +3801,7 @@ dbus_message_get_is_error (DBusMessage *message)
_dbus_return_val_if_fail (message != NULL, FALSE);
- header = _dbus_string_get_const_data_len (&message->header, 1, 1);
+ header = _dbus_string_get_const_data_len (&message->header, FLAGS_OFFSET, 1);
return (*header & DBUS_HEADER_FLAG_ERROR) != 0;
}
@@ -4298,6 +4373,9 @@ _dbus_message_loader_return_buffer (DBusMessageLoader *loader,
/**
* Converts buffered data into messages.
*
+ * @todo we need to check that the proper named header fields exist
+ * for each message type.
+ *
* @param loader the loader.
* @returns #TRUE if we had enough memory to finish.
*/
@@ -4311,22 +4389,22 @@ _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
{
DBusMessage *message;
const char *header_data;
- int byte_order, header_len, body_len, header_padding;
+ int byte_order, message_type, header_len, body_len, header_padding;
dbus_uint32_t header_len_unsigned, body_len_unsigned;
header_data = _dbus_string_get_const_data_len (&loader->data, 0, 16);
_dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
- if (header_data[2] != DBUS_MAJOR_PROTOCOL_VERSION)
+ if (header_data[VERSION_OFFSET] != DBUS_MAJOR_PROTOCOL_VERSION)
{
_dbus_verbose ("Message has protocol version %d ours is %d\n",
- (int) header_data[2], DBUS_MAJOR_PROTOCOL_VERSION);
+ (int) header_data[VERSION_OFFSET], DBUS_MAJOR_PROTOCOL_VERSION);
loader->corrupted = TRUE;
return TRUE;
}
- byte_order = header_data[0];
+ byte_order = header_data[BYTE_ORDER_OFFSET];
if (byte_order != DBUS_LITTLE_ENDIAN &&
byte_order != DBUS_BIG_ENDIAN)
@@ -4337,6 +4415,18 @@ _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
return TRUE;
}
+ /* Unknown types are ignored, but INVALID is
+ * disallowed
+ */
+ message_type = header_data[TYPE_OFFSET];
+ if (message_type == DBUS_MESSAGE_TYPE_INVALID)
+ {
+ _dbus_verbose ("Message with bad type '%d' received\n",
+ message_type);
+ loader->corrupted = TRUE;
+ return TRUE;
+ }
+
header_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 4);
body_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 8);
@@ -5821,7 +5911,7 @@ _dbus_message_test (const char *test_data_dir)
_dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
- message = dbus_message_new ("test.Message", "org.freedesktop.DBus.Test");
+ message = dbus_message_new_method_call ("test.Message", "org.freedesktop.DBus.Test");
_dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.Test"));
_dbus_message_set_serial (message, 1234);
dbus_message_set_sender (message, "org.foo.bar");
@@ -5840,7 +5930,7 @@ _dbus_message_test (const char *test_data_dir)
dbus_message_unref (message);
/* Test the vararg functions */
- message = dbus_message_new ("test.Message", "org.freedesktop.DBus.Test");
+ message = dbus_message_new_method_call ("test.Message", "org.freedesktop.DBus.Test");
_dbus_message_set_serial (message, 1);
dbus_message_append_args (message,
DBUS_TYPE_INT32, -0x12345678,
@@ -5906,7 +5996,7 @@ _dbus_message_test (const char *test_data_dir)
dbus_message_unref (message);
dbus_message_unref (copy);
- message = dbus_message_new ("test.Message", "org.freedesktop.DBus.Test");
+ message = dbus_message_new_method_call ("test.Message", "org.freedesktop.DBus.Test");
_dbus_message_set_serial (message, 1);
dbus_message_set_reply_serial (message, 0x12345678);
diff --git a/dbus/dbus-message.h b/dbus/dbus-message.h
index bd52bd1a..d2c14c78 100644
--- a/dbus/dbus-message.h
+++ b/dbus/dbus-message.h
@@ -57,17 +57,19 @@ struct DBusMessageIter
void *pad3;
};
+DBusMessage* dbus_message_new_method_call (const char *name,
+ const char *destination_service);
+DBusMessage* dbus_message_new_method_return (DBusMessage *method_call);
+DBusMessage* dbus_message_new_signal (const char *name);
+DBusMessage* dbus_message_new_error (DBusMessage *reply_to,
+ const char *error_name,
+ const char *error_message);
-DBusMessage* dbus_message_new (const char *name,
- const char *destination_service);
-DBusMessage* dbus_message_new_reply (DBusMessage *original_message);
-DBusMessage* dbus_message_new_error_reply (DBusMessage *original_message,
- const char *error_name,
- const char *error_message);
-DBusMessage *dbus_message_copy (const DBusMessage *message);
+DBusMessage *dbus_message_copy (const DBusMessage *message);
void dbus_message_ref (DBusMessage *message);
void dbus_message_unref (DBusMessage *message);
+int dbus_message_get_type (DBusMessage *message);
const char* dbus_message_get_name (DBusMessage *message);
const char* dbus_message_get_destination (DBusMessage *message);
dbus_bool_t dbus_message_set_sender (DBusMessage *message,
diff --git a/dbus/dbus-object-registry.c b/dbus/dbus-object-registry.c
index a550f8e2..a4d92216 100644
--- a/dbus/dbus-object-registry.c
+++ b/dbus/dbus-object-registry.c
@@ -24,6 +24,7 @@
#include "dbus-connection-internal.h"
#include "dbus-internals.h"
#include "dbus-hash.h"
+#include "dbus-protocol.h"
#include <string.h>
/**
@@ -599,12 +600,64 @@ _dbus_object_registry_remove_and_unlock (DBusObjectRegistry *registry,
(* vtable->unregistered) (&info);
}
+/**
+ * Handle a message, passing it to any objects in the registry that
+ * should receive it.
+ *
+ * @todo handle messages to an object ID, not just those to
+ * an interface name.
+ *
+ * @param registry the object registry
+ * @param message the message to handle
+ * @returns what to do with the message next
+ */
DBusHandlerResult
_dbus_object_registry_handle_and_unlock (DBusObjectRegistry *registry,
DBusMessage *message)
{
- /* FIXME */
- return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
+ DBusInterfaceEntry *iface_entry;
+ DBusObjectEntry *object_entry;
+ DBusObjectInfo info;
+ const DBusObjectVTable *vtable;
+
+ _dbus_assert (registry != NULL);
+ _dbus_assert (message != NULL);
+
+ if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
+ return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
+
+ /* If the message isn't to a specific object ID, we send
+ * it to the first object that supports the given interface.
+ */
+ iface_entry = lookup_interface (registry,
+ dbus_message_get_name (message),
+ FALSE);
+
+ if (iface_entry == NULL)
+ return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
+
+ _dbus_assert (iface_entry->n_objects > 0);
+ _dbus_assert (iface_entry->objects != NULL);
+
+ object_entry = &registry->entries[iface_entry->objects[0]];
+
+
+ /* Once we have an object entry, pass message to the object */
+
+ _dbus_assert (object_entry->vtable != NULL);
+
+ info_from_entry (registry, &info, object_entry);
+ vtable = object_entry->vtable;
+
+ /* Drop lock and invoke application code */
+#ifdef DBUS_BUILD_TESTS
+ if (registry->connection)
+#endif
+ _dbus_connection_unlock (registry->connection);
+
+ (* vtable->message) (&info, message);
+
+ return DBUS_HANDLER_RESULT_REMOVE_MESSAGE;
}
void
@@ -665,6 +718,7 @@ add_and_remove_objects (DBusObjectRegistry *registry)
"org.freedesktop.Test.Foo",
NULL };
int i;
+ DBusMessage *message;
i = 0;
while (i < N_OBJECTS)
@@ -761,6 +815,33 @@ add_and_remove_objects (DBusObjectRegistry *registry)
++i;
}
+ message = dbus_message_new_method_call ("org.freedesktop.Test.Foo", NULL);
+ if (message != NULL)
+ {
+ if (_dbus_object_registry_handle_and_unlock (registry, message) !=
+ DBUS_HANDLER_RESULT_REMOVE_MESSAGE)
+ _dbus_assert_not_reached ("message not handled\n");
+ dbus_message_unref (message);
+ }
+
+ message = dbus_message_new_method_call ("org.freedesktop.Test.Blah", NULL);
+ if (message != NULL)
+ {
+ if (_dbus_object_registry_handle_and_unlock (registry, message) !=
+ DBUS_HANDLER_RESULT_REMOVE_MESSAGE)
+ _dbus_assert_not_reached ("message not handled\n");
+ dbus_message_unref (message);
+ }
+
+ message = dbus_message_new_method_call ("org.freedesktop.Test.NotRegisteredIface", NULL);
+ if (message != NULL)
+ {
+ if (_dbus_object_registry_handle_and_unlock (registry, message) !=
+ DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS)
+ _dbus_assert_not_reached ("message handled but no handler was registered\n");
+ dbus_message_unref (message);
+ }
+
i = 0;
while (i < (N_OBJECTS - 30))
{
diff --git a/dbus/dbus-object.c b/dbus/dbus-object.c
index c3f1536d..5582f94a 100644
--- a/dbus/dbus-object.c
+++ b/dbus/dbus-object.c
@@ -273,6 +273,10 @@ dbus_callback_object_set_data (DBusCallbackObject *callback,
* Sets the function to be used to handle messages to the
* callback object.
*
+ * @todo the thread locking on DBusCallbackObject is hosed; in this
+ * function in particular it's a joke since we don't take the same
+ * lock when _calling_ the callback function.
+ *
* @param callback the callback
* @param function the function
*/
@@ -287,7 +291,6 @@ dbus_callback_object_set_function (DBusCallbackObject *callback,
_DBUS_UNLOCK (callback_object);
}
-
/** @} */
#ifdef DBUS_BUILD_TESTS
diff --git a/dbus/dbus-protocol.h b/dbus/dbus-protocol.h
index 04988862..dcb7a042 100644
--- a/dbus/dbus-protocol.h
+++ b/dbus/dbus-protocol.h
@@ -61,6 +61,7 @@ extern "C" {
#define DBUS_MAXIMUM_NAME_LENGTH 256
/* Types of message */
+#define DBUS_MESSAGE_TYPE_INVALID 0
#define DBUS_MESSAGE_TYPE_METHOD_CALL 1
#define DBUS_MESSAGE_TYPE_METHOD_RETURN 2
#define DBUS_MESSAGE_TYPE_ERROR 3
diff --git a/doc/dbus-specification.sgml b/doc/dbus-specification.sgml
index 68a71cec..a53be53d 100644
--- a/doc/dbus-specification.sgml
+++ b/doc/dbus-specification.sgml
@@ -135,6 +135,12 @@
</row>
<row>
<entry>1 byte</entry>
+ <entry>Type of message. Unknown types MUST be ignored.
+ Currently-defined types are described below.
+ </entry>
+ </row>
+ <row>
+ <entry>1 byte</entry>
<entry>Bitwise OR of flags. Unknown flags
MUST be ignored. Currently-defined flags are described below.
</entry>
@@ -149,12 +155,6 @@
</entry>
</row>
<row>
- <entry>1 byte</entry>
- <entry>A nul byte, reserved for future use.
- Any value for this byte MUST be accepted.
- </entry>
- </row>
- <row>
<entry>4 bytes</entry>
<entry>An unsigned 32-bit integer in the
message's byte order, indicating the total length in bytes of
@@ -182,7 +182,44 @@
</informaltable>
</para>
<para>
- Flags that can appear in the second byte of the header:
+ Types that can appear in the second byte of the header:
+ <informaltable>
+ <tgroup cols=2>
+ <thead>
+ <row>
+ <entry>Decimal value</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>0</entry>
+ <entry>This is an invalid type, if seen in a message
+ the connection should be dropped immediately.</entry>
+ </row>
+ <row>
+ <entry>1</entry>
+ <entry>Method call.</entry>
+ </row>
+ </row>
+ <row>
+ <entry>2</entry>
+ <entry>Method reply with returned data.</entry>
+ </row>
+ <row>
+ <entry>3</entry>
+ <entry>Error.</entry>
+ </row>
+ <row>
+ <entry>4</entry>
+ <entry>Signal emission.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ <para>
+ Flags that can appear in the third byte of the header:
<informaltable>
<tgroup cols=2>
<thead>
@@ -196,6 +233,13 @@
<entry>0x1</entry>
<entry>This message is an error reply. If the first argument exists and is a string, it is an error message.</entry>
</row>
+ <row>
+ <entry>0x2</entry>
+ <entry>This message does not expect method return replies or
+ error replies; the reply can be omitted as an
+ optimization. However, it is compliant with this specification
+ to return the reply despite this flag.</entry>
+ </row>
</tbody>
</tgroup>
</informaltable>
diff --git a/test/data/invalid-messages/bad-endian.message b/test/data/invalid-messages/bad-endian.message
index 7a7b75d1..b1432359 100644
--- a/test/data/invalid-messages/bad-endian.message
+++ b/test/data/invalid-messages/bad-endian.message
@@ -1,7 +1,7 @@
## message with invalid endianness tag
BYTE 'i'
-BYTE 0
+BYTE 1
BYTE 0
BYTE 0
LENGTH Header
diff --git a/test/data/valid-messages/simplest-manual.message b/test/data/valid-messages/simplest-manual.message
index 8eed1e5f..f0ecccdd 100644
--- a/test/data/valid-messages/simplest-manual.message
+++ b/test/data/valid-messages/simplest-manual.message
@@ -3,7 +3,7 @@
LITTLE_ENDIAN
BYTE 'l'
-BYTE 0
+BYTE 1
BYTE 0
BYTE 0
LENGTH Header