Commit ff5283ab authored by Havoc Pennington's avatar Havoc Pennington

2002-12-26 Havoc Pennington <hp@pobox.com>

	* dbus/dbus-marshal.h (DBUS_COMPILER_BYTE_ORDER): #ifdef
	WORDS_BIGENDIAN then compiler byte order is DBUS_BIG_ENDIAN,
	doh

	* dbus/dbus-marshal.c: Add macros to do int swapping in-place and
	avoid swap_bytes() overhead (ignoring possible assembly stuff for
	now). Main point is because I wanted unpack_uint32 to implement
	_dbus_verbose_bytes
	(_dbus_verbose_bytes): new function

	* dbus/dbus-string.c (_dbus_string_validate_ascii): new function

	* dbus/dbus-message.c (_dbus_message_loader_get_is_corrupted): add
	mechanism to handle a corrupt message stream
	(_dbus_message_loader_new): fix preallocation to only prealloc,
	not prelengthen

	* dbus/dbus-string.c (_dbus_string_skip_blank): fix this function
	(_dbus_string_test): enhance tests for copy/move and fix the
	functions

	* dbus/dbus-transport-unix.c: Hold references in more places to
	avoid reentrancy problems

	* dbus/dbus-transport.c: ditto

	* dbus/dbus-connection.c (dbus_connection_dispatch_message): don't
	leak reference count in no-message case

	* test/watch.c (do_mainloop): handle adding/removing watches
	during iteration over the watches. Also, ref the connection/server
	stored on a watch, so we don't try to mangle a destroyed one.

	* dbus/dbus-transport-unix.c (do_authentication): perform
	authentication

	* dbus/dbus-auth.c (get_state): add a state
	AUTHENTICATED_WITH_UNUSED_BYTES and return it if required
	(_dbus_auth_get_unused_bytes): append the unused bytes
	to the passed in string, rather than prepend

	* dbus/dbus-transport.c (_dbus_transport_init_base): create
	the auth conversation DBusAuth

	* dbus/dbus-transport-unix.c (_dbus_transport_new_for_fd)
	(_dbus_transport_new_for_domain_socket): when creating a
	transport, pass in whether it's a client-side or server-side
	transport so we know which DBusAuth to create
parent f3729626
2002-12-26 Havoc Pennington <hp@pobox.com>
* dbus/dbus-marshal.h (DBUS_COMPILER_BYTE_ORDER): #ifdef
WORDS_BIGENDIAN then compiler byte order is DBUS_BIG_ENDIAN,
doh
* dbus/dbus-marshal.c: Add macros to do int swapping in-place and
avoid swap_bytes() overhead (ignoring possible assembly stuff for
now). Main point is because I wanted unpack_uint32 to implement
_dbus_verbose_bytes
(_dbus_verbose_bytes): new function
* dbus/dbus-string.c (_dbus_string_validate_ascii): new function
* dbus/dbus-message.c (_dbus_message_loader_get_is_corrupted): add
mechanism to handle a corrupt message stream
(_dbus_message_loader_new): fix preallocation to only prealloc,
not prelengthen
* dbus/dbus-string.c (_dbus_string_skip_blank): fix this function
(_dbus_string_test): enhance tests for copy/move and fix the
functions
* dbus/dbus-transport-unix.c: Hold references in more places to
avoid reentrancy problems
* dbus/dbus-transport.c: ditto
* dbus/dbus-connection.c (dbus_connection_dispatch_message): don't
leak reference count in no-message case
* test/watch.c (do_mainloop): handle adding/removing watches
during iteration over the watches. Also, ref the connection/server
stored on a watch, so we don't try to mangle a destroyed one.
* dbus/dbus-transport-unix.c (do_authentication): perform
authentication
* dbus/dbus-auth.c (get_state): add a state
AUTHENTICATED_WITH_UNUSED_BYTES and return it if required
(_dbus_auth_get_unused_bytes): append the unused bytes
to the passed in string, rather than prepend
* dbus/dbus-transport.c (_dbus_transport_init_base): create
the auth conversation DBusAuth
* dbus/dbus-transport-unix.c (_dbus_transport_new_for_fd)
(_dbus_transport_new_for_domain_socket): when creating a
transport, pass in whether it's a client-side or server-side
transport so we know which DBusAuth to create
2002-12-03 Havoc Pennington <hp@pobox.com>
* dbus/dbus-transport-unix.c (unix_finalize): finalize base
_after_ finalizing the derived members
(unix_connection_set): unref watch if we fail to add it
* dbus/dbus-connection.c (dbus_connection_unref): delete the
transport first, so that the connection owned by the
transport will be valid as the transport finalizes.
* dbus/dbus-transport-unix.c (unix_finalize): free the write_watch
if necessary, and remove watches from the connection.
* dbus/dbus-watch.c (_dbus_watch_list_free): improve a comment
2002-12-26 Anders Carlsson <andersca@codefactory.se>
* dbus/dbus-marshal.c: (_dbus_marshal_string),
......
......@@ -255,7 +255,12 @@ get_state (DBusAuth *auth)
if (auth->need_disconnect)
return DBUS_AUTH_STATE_NEED_DISCONNECT;
else if (auth->authenticated)
return DBUS_AUTH_STATE_AUTHENTICATED;
{
if (_dbus_string_get_length (&auth->incoming) > 0)
return DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES;
else
return DBUS_AUTH_STATE_AUTHENTICATED;
}
else if (auth->needed_memory)
return DBUS_AUTH_STATE_WAITING_FOR_MEMORY;
else if (_dbus_string_get_length (&auth->outgoing) > 0)
......@@ -272,7 +277,10 @@ shutdown_mech (DBusAuth *auth)
auth->authenticated = FALSE;
if (auth->mech != NULL)
{
{
_dbus_verbose ("Shutting down mechanism %s\n",
auth->mech->mechanism);
if (DBUS_AUTH_IS_CLIENT (auth))
(* auth->mech->client_shutdown_func) (auth);
else
......@@ -483,6 +491,9 @@ process_auth (DBusAuth *auth,
auth->mech = find_mech (&mech);
if (auth->mech != NULL)
{
_dbus_verbose ("Trying mechanism %s\n",
auth->mech->mechanism);
if (!(* auth->mech->server_data_func) (auth,
&decoded_response))
goto failed;
......@@ -578,6 +589,7 @@ process_error_server (DBusAuth *auth,
return TRUE;
}
/* return FALSE if no memory, TRUE if all OK */
static dbus_bool_t
get_word (const DBusString *str,
int *start,
......@@ -585,9 +597,10 @@ get_word (const DBusString *str,
{
int i;
_dbus_string_skip_blank (str, *start, start);
_dbus_string_find_blank (str, *start, &i);
if (i != *start)
if (i > *start)
{
if (!_dbus_string_copy_len (str, *start, i, word, 0))
return FALSE;
......@@ -616,7 +629,7 @@ process_mechanisms (DBusAuth *auth,
{
DBusString m;
const DBusAuthMechanismHandler *mech;
if (!_dbus_string_init (&m, _DBUS_INT_MAX))
goto nomem;
......@@ -635,11 +648,24 @@ process_mechanisms (DBusAuth *auth,
* preference. Of course when the server is us,
* it lists things in that order anyhow.
*/
_dbus_verbose ("Adding mechanism %s to list we will try\n",
mech->mechanism);
if (!_dbus_list_append (& DBUS_AUTH_CLIENT (auth)->mechs_to_try,
(void*) mech))
goto nomem;
}
else
{
const char *s;
_dbus_string_get_const_data (&m, &s);
_dbus_verbose ("Server offered mechanism \"%s\" that we don't know how to use\n",
s);
}
_dbus_string_free (&m);
}
auth->already_got_mechanisms = TRUE;
......@@ -706,7 +732,11 @@ process_rejected (DBusAuth *auth,
return FALSE;
}
auth->mech = mech;
_dbus_list_pop_first (& DBUS_AUTH_CLIENT (auth)->mechs_to_try);
_dbus_verbose ("Trying mechanism %s\n",
auth->mech->mechanism);
}
else
{
......@@ -815,25 +845,53 @@ process_command (DBusAuth *auth)
auth->needed_memory = TRUE;
return FALSE;
}
if (eol > _DBUS_ONE_MEGABYTE)
{
/* This is a giant line, someone is trying to hose us. */
if (!_dbus_string_append (&auth->outgoing, "ERROR \"Command too long\"\r\n"))
goto out;
else
goto next_command;
}
if (!_dbus_string_copy_len (&auth->incoming, 0, eol, &command, 0))
goto out;
if (!_dbus_string_validate_ascii (&command, 0,
_dbus_string_get_length (&command)))
{
_dbus_verbose ("Command contained non-ASCII chars or embedded nul\n");
if (!_dbus_string_append (&auth->outgoing, "ERROR \"Command contained non-ASCII\"\r\n"))
goto out;
else
goto next_command;
}
{
const char *q;
_dbus_string_get_const_data (&command, &q);
_dbus_verbose ("got command \"%s\"\n", q);
}
_dbus_string_find_blank (&command, 0, &i);
_dbus_string_skip_blank (&command, i, &j);
if (i != j)
_dbus_string_delete (&command, i, j);
if (j > i)
_dbus_string_delete (&command, i, j - i);
if (!_dbus_string_move (&command, i, &args, 0))
goto out;
i = 0;
while (auth->handlers[i].command != NULL)
{
if (_dbus_string_equal_c_str (&command,
auth->handlers[i].command))
{
_dbus_verbose ("Processing auth command %s\n",
auth->handlers[i].command);
if (!(* auth->handlers[i].func) (auth, &command, &args))
goto out;
......@@ -847,6 +905,8 @@ process_command (DBusAuth *auth)
if (!process_unknown (auth, &command, &args))
goto out;
}
next_command:
/* We've succeeded in processing the whole command so drop it out
* of the incoming buffer and return TRUE to try another command.
......@@ -1002,6 +1062,15 @@ _dbus_auth_do_work (DBusAuth *auth)
_dbus_verbose ("Disconnecting due to excessive data buffered in auth phase\n");
break;
}
if (auth->mech == NULL &&
auth->already_got_mechanisms &&
DBUS_AUTH_CLIENT (auth)->mechs_to_try == NULL)
{
auth->need_disconnect = TRUE;
_dbus_verbose ("Disconnecting because we are out of mechanisms to try using\n");
break;
}
}
while (process_command (auth));
......@@ -1009,40 +1078,54 @@ _dbus_auth_do_work (DBusAuth *auth)
}
/**
* Gets bytes that need to be sent to the
* peer we're conversing with.
* Gets bytes that need to be sent to the peer we're conversing with.
* After writing some bytes, _dbus_auth_bytes_sent() must be called
* to notify the auth object that they were written.
*
* @param auth the auth conversation
* @param str initialized string object to be filled in with bytes to send
* @returns #FALSE if not enough memory to fill in the bytes
* @param str return location for a ref to the buffer to send
* @returns #FALSE if nothing to send
*/
dbus_bool_t
_dbus_auth_get_bytes_to_send (DBusAuth *auth,
DBusString *str)
_dbus_auth_get_bytes_to_send (DBusAuth *auth,
const DBusString **str)
{
_dbus_assert (auth != NULL);
_dbus_assert (str != NULL);
*str = NULL;
if (DBUS_AUTH_IN_END_STATE (auth))
return FALSE;
auth->needed_memory = FALSE;
_dbus_string_set_length (str, 0);
if (_dbus_string_get_length (&auth->outgoing) == 0)
return FALSE;
if (!_dbus_string_move (&auth->outgoing,
0, str, 0))
{
auth->needed_memory = TRUE;
return FALSE;
}
*str = &auth->outgoing;
if (auth->authenticated_pending_output)
auth->authenticated = TRUE;
return TRUE;
}
/**
* Notifies the auth conversation object that
* the given number of bytes of the outgoing buffer
* have been written out.
*
* @param auth the auth conversation
* @param bytes_sent number of bytes written out
*/
void
_dbus_auth_bytes_sent (DBusAuth *auth,
int bytes_sent)
{
_dbus_string_delete (&auth->outgoing,
0, bytes_sent);
if (auth->authenticated_pending_output &&
_dbus_string_get_length (&auth->outgoing) == 0)
auth->authenticated = TRUE;
}
/**
* Stores bytes received from the peer we're conversing with.
*
......@@ -1082,7 +1165,7 @@ _dbus_auth_bytes_received (DBusAuth *auth,
* succeeded.
*
* @param auth the auth conversation
* @param str string to place the unused bytes in
* @param str string to append the unused bytes to
* @returns #FALSE if not enough memory to return the bytes
*/
dbus_bool_t
......@@ -1093,7 +1176,8 @@ _dbus_auth_get_unused_bytes (DBusAuth *auth,
return FALSE;
if (!_dbus_string_move (&auth->incoming,
0, str, 0))
0, str,
_dbus_string_get_length (str)))
return FALSE;
return TRUE;
......
......@@ -37,6 +37,7 @@ typedef enum
DBUS_AUTH_STATE_WAITING_FOR_MEMORY,
DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND,
DBUS_AUTH_STATE_NEED_DISCONNECT,
DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES,
DBUS_AUTH_STATE_AUTHENTICATED
} DBusAuthState;
......@@ -45,8 +46,10 @@ DBusAuth* _dbus_auth_client_new (void);
void _dbus_auth_ref (DBusAuth *auth);
void _dbus_auth_unref (DBusAuth *auth);
DBusAuthState _dbus_auth_do_work (DBusAuth *auth);
dbus_bool_t _dbus_auth_get_bytes_to_send (DBusAuth *auth,
DBusString *str);
dbus_bool_t _dbus_auth_get_bytes_to_send (DBusAuth *auth,
const DBusString **str);
void _dbus_auth_bytes_sent (DBusAuth *auth,
int bytes_sent);
dbus_bool_t _dbus_auth_bytes_received (DBusAuth *auth,
const DBusString *str);
dbus_bool_t _dbus_auth_get_unused_bytes (DBusAuth *auth,
......
......@@ -94,13 +94,18 @@ dbus_bool_t
_dbus_connection_queue_received_message (DBusConnection *connection,
DBusMessage *message)
{
_dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
if (!_dbus_list_append (&connection->incoming_messages,
message))
return FALSE;
dbus_message_ref (message);
connection->n_incoming += 1;
_dbus_verbose ("Incoming message %p added to queue, %d incoming\n",
message, connection->n_incoming);
return TRUE;
}
......@@ -140,11 +145,17 @@ void
_dbus_connection_message_sent (DBusConnection *connection,
DBusMessage *message)
{
_dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
_dbus_assert (message == _dbus_list_get_last (&connection->outgoing_messages));
_dbus_list_pop_last (&connection->outgoing_messages);
dbus_message_unref (message);
connection->n_outgoing -= 1;
_dbus_verbose ("Message %p removed from outgoing queue, %d left to send\n",
message, connection->n_outgoing);
if (connection->n_outgoing == 0)
_dbus_transport_messages_pending (connection->transport,
connection->n_outgoing);
......@@ -164,10 +175,11 @@ dbus_bool_t
_dbus_connection_add_watch (DBusConnection *connection,
DBusWatch *watch)
{
return _dbus_watch_list_add_watch (connection->watches,
watch);
return TRUE;
if (connection->watches) /* null during finalize */
return _dbus_watch_list_add_watch (connection->watches,
watch);
else
return FALSE;
}
/**
......@@ -182,8 +194,9 @@ void
_dbus_connection_remove_watch (DBusConnection *connection,
DBusWatch *watch)
{
_dbus_watch_list_remove_watch (connection->watches,
watch);
if (connection->watches) /* null during finalize */
_dbus_watch_list_remove_watch (connection->watches,
watch);
}
static void
......@@ -442,7 +455,8 @@ dbus_connection_unref (DBusConnection *connection)
NULL, NULL, NULL);
_dbus_watch_list_free (connection->watches);
connection->watches = NULL;
_dbus_hash_iter_init (connection->handler_table, &iter);
while (_dbus_hash_iter_next (&iter))
{
......@@ -545,6 +559,9 @@ dbus_connection_send_message (DBusConnection *connection,
dbus_message_ref (message);
connection->n_outgoing += 1;
_dbus_verbose ("Message %p added to outgoing queue, %d pending to send\n",
message, connection->n_outgoing);
_dbus_message_lock (message);
if (connection->n_outgoing == 1)
......@@ -668,8 +685,15 @@ dbus_connection_pop_message (DBusConnection *connection)
{
if (connection->n_incoming > 0)
{
DBusMessage *message;
message = _dbus_list_pop_first (&connection->incoming_messages);
connection->n_incoming -= 1;
return _dbus_list_pop_first (&connection->incoming_messages);
_dbus_verbose ("Incoming message %p removed from queue, %d incoming\n",
message, connection->n_incoming);
return message;
}
else
return NULL;
......@@ -700,7 +724,10 @@ dbus_connection_dispatch_message (DBusConnection *connection)
message = dbus_connection_pop_message (connection);
if (message == NULL)
return FALSE;
{
dbus_connection_unref (connection);
return FALSE;
}
filter_serial = connection->filters_serial;
handler_serial = connection->handlers_serial;
......
......@@ -74,6 +74,8 @@ char* _dbus_strdup (const char *str);
#define _DBUS_INT_MIN (-_DBUS_INT_MAX - 1)
#define _DBUS_INT_MAX 2147483647
#define _DBUS_MAX_SUN_PATH_LENGTH 99
#define _DBUS_ONE_KILOBYTE 1024
#define _DBUS_ONE_MEGABYTE 1024 * _DBUS_ONE_KILOBYTE
typedef void (* DBusForeachFunction) (void *element,
void *data);
......@@ -81,6 +83,9 @@ typedef void (* DBusForeachFunction) (void *element,
dbus_bool_t _dbus_set_fd_nonblocking (int fd,
DBusResultCode *result);
void _dbus_verbose_bytes (const unsigned char *data,
int len);
DBUS_END_DECLS;
#endif /* DBUS_INTERNALS_H */
......@@ -26,9 +26,37 @@
#include <string.h>
#define DBUS_UINT32_SWAP_LE_BE_CONSTANT(val) ((dbus_uint32_t) ( \
(((dbus_uint32_t) (val) & (dbus_uint32_t) 0x000000ffU) << 24) | \
(((dbus_uint32_t) (val) & (dbus_uint32_t) 0x0000ff00U) << 8) | \
(((dbus_uint32_t) (val) & (dbus_uint32_t) 0x00ff0000U) >> 8) | \
(((dbus_uint32_t) (val) & (dbus_uint32_t) 0xff000000U) >> 24)))
#define DBUS_UINT32_SWAP_LE_BE(val) (DBUS_UINT32_SWAP_LE_BE_CONSTANT (val))
#ifdef WORDS_BIGENDIAN
#define DBUS_INT32_TO_BE(val) ((dbus_int32_t) (val))
#define DBUS_UINT32_TO_BE(val) ((dbus_uint32_t) (val))
#define DBUS_INT32_TO_LE(val) ((dbus_int32_t) DBUS_UINT32_SWAP_LE_BE (val))
#define DBUS_UINT32_TO_LE(val) (DBUS_UINT32_SWAP_LE_BE (val))
#else
#define DBUS_INT32_TO_LE(val) ((dbus_int32_t) (val))
#define DBUS_UINT32_TO_LE(val) ((dbus_uint32_t) (val))
#define DBUS_INT32_TO_BE(val) ((dbus_int32_t) DBUS_UINT32_SWAP_LE_BE (val))
#define DBUS_UINT32_TO_BE(val) (DBUS_UINT32_SWAP_LE_BE (val))
#endif
/* The transformation is symmetric, so the FROM just maps to the TO. */
#define DBUS_INT32_FROM_LE(val) (DBUS_INT32_TO_LE (val))
#define DBUS_UINT32_FROM_LE(val) (DBUS_UINT32_TO_LE (val))
#define DBUS_INT32_FROM_BE(val) (DBUS_INT32_TO_BE (val))
#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. */
* E.g. align to an 8-byte boundary with argument of 8.
*/
/*
* (this + boundary - 1)
......@@ -61,6 +89,41 @@ swap_bytes (unsigned char *data,
}
}
static dbus_uint32_t
unpack_uint32 (int byte_order,
const unsigned char *data)
{
_dbus_assert (DBUS_ALIGN_ADDRESS (data, 4) == data);
if (byte_order == DBUS_LITTLE_ENDIAN)
return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
else
return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
}
static dbus_int32_t
unpack_int32 (int byte_order,
const unsigned char *data)
{
_dbus_assert (DBUS_ALIGN_ADDRESS (data, 4) == data);
if (byte_order == DBUS_LITTLE_ENDIAN)
return DBUS_INT32_FROM_LE (*(dbus_int32_t*)data);
else
return DBUS_INT32_FROM_BE (*(dbus_int32_t*)data);
}
/**
* @defgroup DBusMarshal marshaling and unmarshaling
* @ingroup DBusInternals
* @brief functions to marshal/unmarshal data from the wire
*
* Types and functions related to converting primitive data types from
* wire format to native machine format, and vice versa.
*
* @{
*/
dbus_bool_t
_dbus_marshal_double (DBusString *str,
int byte_order,
......@@ -161,20 +224,14 @@ _dbus_demarshal_int32 (DBusString *str,
int pos,
int *new_pos)
{
dbus_int32_t retval;
const char *buffer;
_dbus_string_get_const_data_len (str, &buffer, pos, sizeof (dbus_int32_t));
retval = *(dbus_int32_t *)buffer;
if (byte_order != DBUS_COMPILER_BYTE_ORDER)
swap_bytes ((unsigned char *)&retval, sizeof (dbus_int32_t));
if (new_pos)
*new_pos = pos + sizeof (dbus_int32_t);
return retval;
return unpack_int32 (byte_order, buffer);
}
dbus_uint32_t
......@@ -183,20 +240,14 @@ _dbus_demarshal_uint32 (DBusString *str,
int pos,
int *new_pos)
{
dbus_uint32_t retval;
const char *buffer;
_dbus_string_get_const_data_len (str, &buffer, pos, sizeof (dbus_uint32_t));
retval = *(dbus_uint32_t *)buffer;
if (byte_order != DBUS_COMPILER_BYTE_ORDER)
swap_bytes ((unsigned char *)&retval, sizeof (dbus_uint32_t));
if (new_pos)
*new_pos = pos + sizeof (dbus_uint32_t);
return retval;
return unpack_uint32 (byte_order, buffer);
}
char *
......@@ -229,6 +280,68 @@ _dbus_demarshal_string (DBusString *str,
return retval;
}
/**
* If in verbose mode, print a block of binary data.
*
* @param data the data
* @param len the length of the data
*/
void
_dbus_verbose_bytes (const unsigned char *data,
int len)
{
int i;
const unsigned char *aligned;
/* Print blanks on first row if appropriate */
aligned = DBUS_ALIGN_ADDRESS (data, 4);
if (aligned > data)
aligned -= 4;
_dbus_assert (aligned <= data);
if (aligned != data)
{
_dbus_verbose ("%5d\t%p: ", - (data - aligned), aligned);
while (aligned != data)
{
_dbus_verbose (" ");
++aligned;
}
}
/* now print the bytes */
i = 0;
while (i < len)
{
if (DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
{
_dbus_verbose ("%5d\t%p: ",
i, &data[i]);
}
if (data[i] >= 32 &&
data[i] <= 126)
_dbus_verbose (" '%c' ", data[i]);
else
_dbus_verbose ("0x%s%x ",
data[i] <= 0xf ? "0" : "", data[i]);
++i;
if (DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
{
if (i > 3)
_dbus_verbose ("big: %d little: %d",
unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
_dbus_verbose ("\n");
}
}
_dbus_verbose ("\n");
}
/** @} */
#ifdef DBUS_BUILD_TESTS
......
......@@ -24,14 +24,19 @@
#ifndef DBUS_MARSHAL_H
#define DBUS_MARSHAL_H
#include <config.h>
#include <dbus/dbus-protocol.h>
#include <dbus/dbus-types.h>
#include <dbus/dbus-string.h>
#ifndef PACKAGE
#error "config.h not included here"
#endif
#ifdef WORDS_BIGENDIAN
#define DBUS_COMPILER_BYTE_ORDER DBUS_LITTLE_ENDIAN
#else
#define DBUS_COMPILER_BYTE_ORDER DBUS_BIG_ENDIAN
#else
#define DBUS_COMPILER_BYTE_ORDER DBUS_LITTLE_ENDIAN
#endif
dbus_bool_t _dbus_marshal_double (DBusString *str,
......
......@@ -39,6 +39,7 @@ void _dbus_message_lock (DBusMessage *message);
DBusMessageLoader* _dbus_message_loader_new (void);
void _dbus_message_loader_ref (DBusMessageLoader *loader);
void _dbus_message_loader_unref (DBusMessageLoader *loader);
void _dbus_message_loader_get_buffer (DBusMessageLoader *loader,
DBusString **buffer);
void _dbus_message_loader_return_buffer (DBusMessageLoader *loader,
......@@ -47,6 +48,7 @@ void _dbus_message_loader_return_buffer (DBusMessageLoader
DBusMessage* _dbus_message_loader_pop_message (DBusMessageLoader *loader);
dbus_bool_t _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader);
DBUS_END_DECLS;
......
......@@ -246,6 +246,8 @@ struct DBusMessageLoader
DBusList *messages; /**< Complete messages. */
unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
};
/**
......@@ -284,7 +286,8 @@ _dbus_message_loader_new (void)
}
/* preallocate the buffer for speed, ignore failure */
(void) _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
_dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
_dbus_string_set_length (&loader->data, 0);
return loader;
}
......@@ -376,9 +379,28 @@ _dbus_message_loader_return_buffer (DBusMessageLoader *loader,
loader->buffer_outstanding = FALSE;
if (loader->corrupted)
return;
while (_dbus_string_get_length (&loader->data) >= 7)
{
DBusMessage *message;
const char *d;
_dbus_string_get_const_data (&loader->data, &d);
if (d[0] != 'H' ||