From 0cf4583b5a4772b9c2a381ce78f6e3a3afcf705d Mon Sep 17 00:00:00 2001 From: William Lachance Date: Tue, 21 Apr 2009 13:51:46 -0400 Subject: Bug 19567 - Make marshaling code usable without DBusConnection Some projects want to reuse the DBus message format, without actually going through a DBusConnection. This set of changes makes a few functions from DBusMessage public, and adds a new function to determine the number of bytes needed to demarshal a message. Signed-off-by: Colin Walters --- dbus/dbus-connection.c | 6 ++-- dbus/dbus-message-factory.c | 4 +-- dbus/dbus-message-internal.h | 2 -- dbus/dbus-message-util.c | 16 ++++++++-- dbus/dbus-message.c | 75 ++++++++++++++++++++++++++++++++++++++------ dbus/dbus-message.h | 6 ++++ dbus/dbus-transport-socket.c | 2 +- 7 files changed, 90 insertions(+), 21 deletions(-) diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index d44d728b..947c0afe 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -1950,7 +1950,7 @@ _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *con if (dbus_message_get_serial (message) == 0) { serial = _dbus_connection_get_next_client_serial (connection); - _dbus_message_set_serial (message, serial); + dbus_message_set_serial (message, serial); if (client_serial) *client_serial = serial; } @@ -1963,7 +1963,7 @@ _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *con _dbus_verbose ("Message %p serial is %u\n", message, dbus_message_get_serial (message)); - _dbus_message_lock (message); + dbus_message_lock (message); /* Now we need to run an iteration to hopefully just write the messages * out immediately, and otherwise get them queued up @@ -3208,7 +3208,7 @@ dbus_connection_send_with_reply (DBusConnection *connection, if (serial == 0) { serial = _dbus_connection_get_next_client_serial (connection); - _dbus_message_set_serial (message, serial); + dbus_message_set_serial (message, serial); } if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial)) diff --git a/dbus/dbus-message-factory.c b/dbus/dbus-message-factory.c index ceffc764..8550ee86 100644 --- a/dbus/dbus-message-factory.c +++ b/dbus/dbus-message-factory.c @@ -222,8 +222,8 @@ generate_from_message (DBusString *data, DBusValidity *expected_validity, DBusMessage *message) { - _dbus_message_set_serial (message, 1); - _dbus_message_lock (message); + dbus_message_set_serial (message, 1); + dbus_message_lock (message); *expected_validity = DBUS_VALID; diff --git a/dbus/dbus-message-internal.h b/dbus/dbus-message-internal.h index 76615859..2e995b47 100644 --- a/dbus/dbus-message-internal.h +++ b/dbus/dbus-message-internal.h @@ -37,8 +37,6 @@ void _dbus_message_get_network_data (DBusMessage *message, void _dbus_message_lock (DBusMessage *message); void _dbus_message_unlock (DBusMessage *message); -void _dbus_message_set_serial (DBusMessage *message, - dbus_uint32_t serial); dbus_bool_t _dbus_message_add_size_counter (DBusMessage *message, DBusCounter *counter); void _dbus_message_add_size_counter_link (DBusMessage *message, diff --git a/dbus/dbus-message-util.c b/dbus/dbus-message-util.c index 0fa010cc..46cbe4e3 100644 --- a/dbus/dbus-message-util.c +++ b/dbus/dbus-message-util.c @@ -949,7 +949,7 @@ _dbus_message_test (const char *test_data_dir) "TestMethod")); _dbus_assert (strcmp (dbus_message_get_path (message), "/org/freedesktop/TestPath") == 0); - _dbus_message_set_serial (message, 1234); + dbus_message_set_serial (message, 1234); /* string length including nul byte not a multiple of 4 */ if (!dbus_message_set_sender (message, "org.foo.bar1")) @@ -1041,7 +1041,7 @@ _dbus_message_test (const char *test_data_dir) "/org/freedesktop/TestPath", "Foo.TestInterface", "TestMethod"); - _dbus_message_set_serial (message, 1); + dbus_message_set_serial (message, 1); dbus_message_set_reply_serial (message, 5678); v_INT16 = -0x123; @@ -1172,7 +1172,7 @@ _dbus_message_test (const char *test_data_dir) dbus_message_unref (copy); /* Message loader test */ - _dbus_message_lock (message); + dbus_message_lock (message); loader = _dbus_message_loader_new (); /* check ref/unref */ @@ -1226,6 +1226,7 @@ _dbus_message_test (const char *test_data_dir) DBusError error = DBUS_ERROR_INIT; char *marshalled = NULL; int len = 0; + char garbage_header[DBUS_MINIMUM_HEADER_SIZE] = "xxx"; if (!dbus_message_marshal (message, &marshalled, &len)) _dbus_assert_not_reached ("failed to marshal message"); @@ -1233,6 +1234,7 @@ _dbus_message_test (const char *test_data_dir) _dbus_assert (len != 0); _dbus_assert (marshalled != NULL); + _dbus_assert (dbus_message_demarshal_bytes_needed (marshalled, len) == len); message2 = dbus_message_demarshal (marshalled, len, &error); _dbus_assert (message2 != NULL); @@ -1255,6 +1257,14 @@ _dbus_message_test (const char *test_data_dir) _dbus_assert (message2 == NULL); _dbus_assert (dbus_error_is_set (&error)); dbus_error_free (&error); + + /* Bytes needed to demarshal empty message: 0 (more) */ + + _dbus_assert (dbus_message_demarshal_bytes_needed ("", 0) == 0); + + /* Bytes needed to demarshal invalid message: -1 (error). */ + + _dbus_assert (dbus_message_demarshal_bytes_needed (garbage_header, DBUS_MINIMUM_HEADER_SIZE) == -1); } dbus_message_unref (message); diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index e2c4771e..edae4258 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -142,7 +142,7 @@ _dbus_message_byteswap (DBusMessage *message) * Gets the data to be sent over the network for this message. * The header and then the body should be written out. * This function is guaranteed to always return the same - * data once a message is locked (with _dbus_message_lock()). + * data once a message is locked (with dbus_message_lock()). * * @param message the message. * @param header return location for message header data. @@ -163,16 +163,19 @@ _dbus_message_get_network_data (DBusMessage *message, * Sets the serial number of a message. * This can only be done once on a message. * + * DBusConnection will automatically set the serial to an appropriate value + * when the message is sent; this function is only needed when encapsulating + * messages in another protocol, or otherwise bypassing DBusConnection. + * * @param message the message * @param serial the serial */ -void -_dbus_message_set_serial (DBusMessage *message, - dbus_uint32_t serial) +void +dbus_message_set_serial (DBusMessage *message, + dbus_uint32_t serial) { - _dbus_assert (message != NULL); - _dbus_assert (!message->locked); - _dbus_assert (dbus_message_get_serial (message) == 0); + _dbus_return_if_fail (message != NULL); + _dbus_return_if_fail (!message->locked); _dbus_header_set_serial (&message->header, serial); } @@ -277,12 +280,13 @@ _dbus_message_remove_size_counter (DBusMessage *message, * reference to a message in the outgoing queue and change it * underneath us. Messages are locked when they enter the outgoing * queue (dbus_connection_send_message()), and the library complains - * if the message is modified while locked. + * if the message is modified while locked. This function may also + * called externally, for applications wrapping D-Bus in another protocol. * * @param message the message to lock. */ void -_dbus_message_lock (DBusMessage *message) +dbus_message_lock (DBusMessage *message) { if (!message->locked) { @@ -3941,7 +3945,7 @@ dbus_message_marshal (DBusMessage *msg, _dbus_return_val_if_fail (msg != NULL, FALSE); _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE); _dbus_return_val_if_fail (len_p != NULL, FALSE); - + if (!_dbus_string_init (&tmp)) return FALSE; @@ -4023,6 +4027,57 @@ dbus_message_demarshal (const char *str, return NULL; } +/** + * Returns the number of bytes required to be in the buffer to demarshal a + * D-Bus message. + * + * Generally, this function is only useful for encapsulating D-Bus messages in + * a different protocol. + * + * @param str data to be marshalled + * @param len the length of str + * @param error the location to save errors to + * @returns -1 if there was no valid data to be demarshalled, 0 if there wasn't enough data to determine how much should be demarshalled. Otherwise returns the number of bytes to be demarshalled + * + */ +int +dbus_message_demarshal_bytes_needed(const char *buf, + int len) +{ + DBusString str; + int byte_order, fields_array_len, header_len, body_len; + DBusValidity validity = DBUS_VALID; + int have_message; + + if (!buf || len < DBUS_MINIMUM_HEADER_SIZE) + return 0; + + if (len > DBUS_MAXIMUM_MESSAGE_LENGTH) + len = DBUS_MAXIMUM_MESSAGE_LENGTH; + _dbus_string_init_const_len (&str, buf, len); + + validity = DBUS_VALID; + have_message + = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH, + &validity, &byte_order, + &fields_array_len, + &header_len, + &body_len, + &str, 0, + len); + _dbus_string_free (&str); + + if (validity == DBUS_VALID) + { + _dbus_assert(have_message); + return header_len + body_len; + } + else + { + return -1; /* broken! */ + } +} + /** @} */ /* tests in dbus-message-util.c */ diff --git a/dbus/dbus-message.h b/dbus/dbus-message.h index 1bf7d0c2..2e29fef0 100644 --- a/dbus/dbus-message.h +++ b/dbus/dbus-message.h @@ -131,6 +131,8 @@ dbus_bool_t dbus_message_has_sender (DBusMessage *message, dbus_bool_t dbus_message_has_signature (DBusMessage *message, const char *signature); dbus_uint32_t dbus_message_get_serial (DBusMessage *message); +void dbus_message_set_serial (DBusMessage *message, + dbus_uint32_t serial); dbus_bool_t dbus_message_set_reply_serial (DBusMessage *message, dbus_uint32_t reply_serial); dbus_uint32_t dbus_message_get_reply_serial (DBusMessage *message); @@ -196,6 +198,7 @@ dbus_bool_t dbus_message_iter_open_container (DBusMessageIter *iter, dbus_bool_t dbus_message_iter_close_container (DBusMessageIter *iter, DBusMessageIter *sub); +void dbus_message_lock (DBusMessage *message); dbus_bool_t dbus_set_error_from_message (DBusError *error, DBusMessage *message); @@ -220,6 +223,9 @@ DBusMessage* dbus_message_demarshal (const char *str, int len, DBusError *error); +int dbus_message_demarshal_bytes_needed (const char *str, + int len); + /** @} */ DBUS_END_DECLS diff --git a/dbus/dbus-transport-socket.c b/dbus/dbus-transport-socket.c index 10b671c2..6d7c89cd 100644 --- a/dbus/dbus-transport-socket.c +++ b/dbus/dbus-transport-socket.c @@ -537,7 +537,7 @@ do_writing (DBusTransport *transport) message = _dbus_connection_get_message_to_send (transport->connection); _dbus_assert (message != NULL); - _dbus_message_lock (message); + dbus_message_lock (message); #if 0 _dbus_verbose ("writing message %p\n", message); -- cgit