Commit 502fbda2 authored by Havoc Pennington's avatar Havoc Pennington

2003-01-18 Havoc Pennington <hp@pobox.com>

	* dbus/dbus-transport-unix.c (unix_do_iteration): only do the
	reading/writing if read_watch != NULL or write_watch != NULL.

	* dbus/dbus-message.c (_dbus_message_loader_return_buffer): fix
	the message loader code to actually load message->header and
	message->body into the newly-created message.

	* dbus/dbus-transport-unix.c (check_write_watch): fix a mem leak
	in OOM case

	* dbus/dbus-connection.c (dbus_connection_set_max_message_size)
	(dbus_connection_get_max_message_size)
	(dbus_connection_set_max_live_messages_size)
	(dbus_connection_get_max_live_messages_size): implement some
	resource limitation functions

	* dbus/dbus-resources.c: new file implementing some of the
	resource limits stuff

	* dbus/dbus-message.c (dbus_message_iter_get_byte_array): add
	missing docs, add @todo to handle OOM etc.

	* dbus/dbus-marshal.c (_dbus_demarshal_byte_array): add missing
	docs
parent 0363701c
2003-01-18 Havoc Pennington <hp@pobox.com>
* dbus/dbus-transport-unix.c (unix_do_iteration): only do the
reading/writing if read_watch != NULL or write_watch != NULL.
* dbus/dbus-message.c (_dbus_message_loader_return_buffer): fix
the message loader code to actually load message->header and
message->body into the newly-created message.
* dbus/dbus-transport-unix.c (check_write_watch): fix a mem leak
in OOM case
* dbus/dbus-connection.c (dbus_connection_set_max_message_size)
(dbus_connection_get_max_message_size)
(dbus_connection_set_max_live_messages_size)
(dbus_connection_get_max_live_messages_size): implement some
resource limitation functions
* dbus/dbus-resources.c: new file implementing some of the
resource limits stuff
* dbus/dbus-message.c (dbus_message_iter_get_byte_array): add
missing docs, add @todo to handle OOM etc.
* dbus/dbus-marshal.c (_dbus_demarshal_byte_array): add missing
docs
2003-01-18 Havoc Pennington <hp@pobox.com> 2003-01-18 Havoc Pennington <hp@pobox.com>
* dbus/dbus-connection.c (dbus_connection_unref): disconnect the * dbus/dbus-connection.c (dbus_connection_unref): disconnect the
......
...@@ -28,6 +28,8 @@ libdbus_1_la_SOURCES= \ ...@@ -28,6 +28,8 @@ libdbus_1_la_SOURCES= \
dbus-message.c \ dbus-message.c \
dbus-message-handler.c \ dbus-message-handler.c \
dbus-message-internal.h \ dbus-message-internal.h \
dbus-resources.c \
dbus-resources.h \
dbus-server.c \ dbus-server.c \
dbus-server-protected.h \ dbus-server-protected.h \
dbus-server-unix.c \ dbus-server-unix.c \
......
/* -*- mode: C; c-file-style: "gnu" -*- */ /* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-connection.c DBusConnection object /* dbus-connection.c DBusConnection object
* *
* Copyright (C) 2002 Red Hat Inc. * Copyright (C) 2002, 2003 Red Hat Inc.
* *
* Licensed under the Academic Free License version 1.2 * Licensed under the Academic Free License version 1.2
* *
...@@ -1274,4 +1274,74 @@ _dbus_connection_free_data_slots (DBusConnection *connection) ...@@ -1274,4 +1274,74 @@ _dbus_connection_free_data_slots (DBusConnection *connection)
connection->n_slots = 0; connection->n_slots = 0;
} }
/**
* Specifies the maximum size message this connection is allowed to
* receive. Larger messages will result in disconnecting the
* connection.
*
* @param connection a #DBusConnection
* @param size maximum message size the connection can receive, in bytes
*/
void
dbus_connection_set_max_message_size (DBusConnection *connection,
long size)
{
_dbus_transport_set_max_message_size (connection->transport,
size);
}
/**
* Gets the value set by dbus_connection_set_max_message_size().
*
* @param connection the connection
* @returns the max size of a single message
*/
long
dbus_connection_get_max_message_size (DBusConnection *connection)
{
return _dbus_transport_get_max_message_size (connection->transport);
}
/**
* Sets the maximum total number of bytes that can be used for all messages
* received on this connection. Messages count toward the maximum until
* they are finalized. When the maximum is reached, the connection will
* not read more data until some messages are finalized.
*
* The semantics of the maximum are: if outstanding messages are
* already above the maximum, additional messages will not be read.
* The semantics are not: if the next message would cause us to exceed
* the maximum, we don't read it. The reason is that we don't know the
* size of a message until after we read it.
*
* Thus, the max live messages size can actually be exceeded
* by up to the maximum size of a single message.
*
* Also, if we read say 1024 bytes off the wire in a single read(),
* and that contains a half-dozen small messages, we may exceed the
* size max by that amount. But this should be inconsequential.
*
* @param connection the connection
* @param size the maximum size in bytes of all outstanding messages
*/
void
dbus_connection_set_max_live_messages_size (DBusConnection *connection,
long size)
{
_dbus_transport_set_max_live_messages_size (connection->transport,
size);
}
/**
* Gets the value set by dbus_connection_set_max_live_messages_size().
*
* @param connection the connection
* @returns the max size of all live messages
*/
long
dbus_connection_get_max_live_messages_size (DBusConnection *connection)
{
return _dbus_transport_get_max_live_messages_size (connection->transport);
}
/** @} */ /** @} */
...@@ -132,6 +132,14 @@ dbus_bool_t dbus_connection_set_data (DBusConnection *connection, ...@@ -132,6 +132,14 @@ dbus_bool_t dbus_connection_set_data (DBusConnection *connection,
void* dbus_connection_get_data (DBusConnection *connection, void* dbus_connection_get_data (DBusConnection *connection,
int slot); int slot);
void dbus_connection_set_max_message_size (DBusConnection *connection,
long size);
long dbus_connection_get_max_message_size (DBusConnection *connection);
void dbus_connection_set_max_live_messages_size (DBusConnection *connection,
long size);
long dbus_connection_get_max_live_messages_size (DBusConnection *connection);
DBUS_END_DECLS; DBUS_END_DECLS;
#endif /* DBUS_CONNECTION_H */ #endif /* DBUS_CONNECTION_H */
...@@ -401,6 +401,19 @@ _dbus_demarshal_string (DBusString *str, ...@@ -401,6 +401,19 @@ _dbus_demarshal_string (DBusString *str,
return retval; return retval;
} }
/**
* Demarshals a byte array.
*
* @todo Should probably demarshal to a DBusString,
* having memcpy() in here is Evil(tm).
*
* @param str the string containing the data
* @param byte_order the byte order
* @param pos the position in the string
* @param new_pos the new position of the string
* @param array_len length of the demarshaled data
* @returns the demarshaled data.
*/
unsigned char * unsigned char *
_dbus_demarshal_byte_array (DBusString *str, _dbus_demarshal_byte_array (DBusString *str,
int byte_order, int byte_order,
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#define DBUS_MESSAGE_INTERNAL_H #define DBUS_MESSAGE_INTERNAL_H
#include <dbus/dbus-message.h> #include <dbus/dbus-message.h>
#include <dbus/dbus-resources.h>
DBUS_BEGIN_DECLS; DBUS_BEGIN_DECLS;
...@@ -38,6 +39,9 @@ void _dbus_message_lock (DBusMessage *message); ...@@ -38,6 +39,9 @@ void _dbus_message_lock (DBusMessage *message);
void _dbus_message_set_client_serial (DBusMessage *message, void _dbus_message_set_client_serial (DBusMessage *message,
dbus_int32_t client_serial); dbus_int32_t client_serial);
void _dbus_message_add_size_counter (DBusMessage *message,
DBusCounter *counter);
DBusMessageLoader* _dbus_message_loader_new (void); DBusMessageLoader* _dbus_message_loader_new (void);
void _dbus_message_loader_ref (DBusMessageLoader *loader); void _dbus_message_loader_ref (DBusMessageLoader *loader);
void _dbus_message_loader_unref (DBusMessageLoader *loader); void _dbus_message_loader_unref (DBusMessageLoader *loader);
...@@ -52,6 +56,10 @@ DBusMessage* _dbus_message_loader_pop_message (DBusMessageLoader ...@@ -52,6 +56,10 @@ DBusMessage* _dbus_message_loader_pop_message (DBusMessageLoader
dbus_bool_t _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader); dbus_bool_t _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader);
void _dbus_message_loader_set_max_message_size (DBusMessageLoader *loader,
long size);
long _dbus_message_loader_get_max_message_size (DBusMessageLoader *loader);
DBUS_END_DECLS; DBUS_END_DECLS;
#endif /* DBUS_MESSAGE_H */ #endif /* DBUS_MESSAGE_H */
/* -*- mode: C; c-file-style: "gnu" -*- */ /* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-message.c DBusMessage object /* dbus-message.c DBusMessage object
* *
* Copyright (C) 2002 Red Hat Inc. * Copyright (C) 2002, 2003 Red Hat Inc.
* Copyright (C) 2002, 2003 CodeFactory AB * Copyright (C) 2002, 2003 CodeFactory AB
* *
* Licensed under the Academic Free License version 1.2 * Licensed under the Academic Free License version 1.2
...@@ -40,13 +40,6 @@ ...@@ -40,13 +40,6 @@
* @{ * @{
*/ */
/**
* The largest-length message we allow
*
* @todo match this up with whatever the protocol spec says.
*/
#define _DBUS_MAX_MESSAGE_LENGTH (_DBUS_INT_MAX/16)
/** /**
* @brief Internals of DBusMessage * @brief Internals of DBusMessage
* *
...@@ -72,6 +65,9 @@ struct DBusMessage ...@@ -72,6 +65,9 @@ struct DBusMessage
dbus_int32_t client_serial; /**< Client serial or -1 if not set */ dbus_int32_t client_serial; /**< Client serial or -1 if not set */
dbus_int32_t reply_serial; /**< Reply serial or -1 if not set */ dbus_int32_t reply_serial; /**< Reply serial or -1 if not set */
DBusCounter *size_counter; /**< Counter for the size of the message, or #NULL */
long size_counter_delta; /**< Size we incremented the size counter by. */
unsigned int locked : 1; /**< Message being sent, no modifications allowed. */ unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
}; };
...@@ -127,6 +123,39 @@ _dbus_message_set_client_serial (DBusMessage *message, ...@@ -127,6 +123,39 @@ _dbus_message_set_client_serial (DBusMessage *message,
message->client_serial = client_serial; message->client_serial = client_serial;
} }
/**
* Adds a counter to be incremented immediately with the
* size of this message, and decremented by the size
* of this message when this message if finalized.
*
* @param message the message
* @param counter the counter
*/
void
_dbus_message_add_size_counter (DBusMessage *message,
DBusCounter *counter)
{
_dbus_assert (message->size_counter == NULL); /* If this fails we may need to keep a list of
* counters instead of just one
*/
message->size_counter = counter;
_dbus_counter_ref (message->size_counter);
/* When we can change message size, we may want to
* update this each time we do so, or we may want to
* just KISS like this.
*/
message->size_counter_delta =
_dbus_string_get_length (&message->header) +
_dbus_string_get_length (&message->body);
_dbus_verbose ("message has size %ld\n",
message->size_counter_delta);
_dbus_counter_adjust (message->size_counter, message->size_counter_delta);
}
static void static void
dbus_message_write_header (DBusMessage *message) dbus_message_write_header (DBusMessage *message)
{ {
...@@ -253,7 +282,7 @@ dbus_message_new (const char *service, ...@@ -253,7 +282,7 @@ dbus_message_new (const char *service,
message->client_serial = -1; message->client_serial = -1;
message->reply_serial = -1; message->reply_serial = -1;
if (!_dbus_string_init (&message->header, _DBUS_MAX_MESSAGE_LENGTH)) if (!_dbus_string_init (&message->header, _DBUS_INT_MAX))
{ {
dbus_free (message->service); dbus_free (message->service);
dbus_free (message->name); dbus_free (message->name);
...@@ -261,7 +290,7 @@ dbus_message_new (const char *service, ...@@ -261,7 +290,7 @@ dbus_message_new (const char *service,
return NULL; return NULL;
} }
if (!_dbus_string_init (&message->body, _DBUS_MAX_MESSAGE_LENGTH)) if (!_dbus_string_init (&message->body, _DBUS_INT_MAX))
{ {
dbus_free (message->service); dbus_free (message->service);
dbus_free (message->name); dbus_free (message->name);
...@@ -302,6 +331,13 @@ dbus_message_unref (DBusMessage *message) ...@@ -302,6 +331,13 @@ dbus_message_unref (DBusMessage *message)
message->refcount -= 1; message->refcount -= 1;
if (message->refcount == 0) if (message->refcount == 0)
{ {
if (message->size_counter != NULL)
{
_dbus_counter_adjust (message->size_counter,
- message->size_counter_delta);
_dbus_counter_unref (message->size_counter);
}
_dbus_string_free (&message->header); _dbus_string_free (&message->header);
_dbus_string_free (&message->body); _dbus_string_free (&message->body);
...@@ -330,7 +366,7 @@ dbus_message_get_name (DBusMessage *message) ...@@ -330,7 +366,7 @@ dbus_message_get_name (DBusMessage *message)
* The list is terminated with 0. * The list is terminated with 0.
* *
* @param message the message * @param message the message
* @param type of the first field * @param first_field_type type of the first field
* @param ... value of first field, list of additional type-value pairs * @param ... value of first field, list of additional type-value pairs
* @returns #TRUE on success * @returns #TRUE on success
*/ */
...@@ -886,8 +922,21 @@ dbus_message_iter_get_double (DBusMessageIter *iter) ...@@ -886,8 +922,21 @@ dbus_message_iter_get_double (DBusMessageIter *iter)
iter->pos + 1, NULL); iter->pos + 1, NULL);
} }
/**
* Returns the byte array that the iterator may point to.
* Note that you need to check that the iterator points
* to a byte array prior to using this function.
*
* @todo this function should probably take "unsigned char **" as
* an out param argument, and return boolean or result code.
*
* @param iter the iterator
* @param len return location for length of byte array
* @returns the byte array
*/
unsigned char * unsigned char *
dbus_message_iter_get_byte_array (DBusMessageIter *iter, int *len) dbus_message_iter_get_byte_array (DBusMessageIter *iter,
int *len)
{ {
_dbus_assert (dbus_message_iter_get_field_type (iter) == DBUS_TYPE_BYTE_ARRAY); _dbus_assert (dbus_message_iter_get_field_type (iter) == DBUS_TYPE_BYTE_ARRAY);
...@@ -926,6 +975,8 @@ struct DBusMessageLoader ...@@ -926,6 +975,8 @@ struct DBusMessageLoader
DBusString data; /**< Buffered data */ DBusString data; /**< Buffered data */
DBusList *messages; /**< Complete messages. */ DBusList *messages; /**< Complete messages. */
long max_message_size; /**< Maximum size of a message */
unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */ unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
...@@ -959,8 +1010,13 @@ _dbus_message_loader_new (void) ...@@ -959,8 +1010,13 @@ _dbus_message_loader_new (void)
if (loader == NULL) if (loader == NULL)
return NULL; return NULL;
loader->refcount = 1; loader->refcount = 1;
/* Try to cap message size at something that won't *totally* hose
* the system if we have a couple of them.
*/
loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
if (!_dbus_string_init (&loader->data, _DBUS_INT_MAX)) if (!_dbus_string_init (&loader->data, _DBUS_INT_MAX))
{ {
dbus_free (loader); dbus_free (loader);
...@@ -1190,10 +1246,10 @@ _dbus_message_loader_return_buffer (DBusMessageLoader *loader, ...@@ -1190,10 +1246,10 @@ _dbus_message_loader_return_buffer (DBusMessageLoader *loader,
header_len = _dbus_unpack_int32 (byte_order, header_data + 4); header_len = _dbus_unpack_int32 (byte_order, header_data + 4);
body_len = _dbus_unpack_int32 (byte_order, header_data + 8); body_len = _dbus_unpack_int32 (byte_order, header_data + 8);
if (header_len + body_len > _DBUS_MAX_MESSAGE_LENGTH) if (header_len + body_len > loader->max_message_size)
{ {
_dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %d\n", _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %d\n",
header_len, body_len, _DBUS_MAX_MESSAGE_LENGTH); header_len, body_len, loader->max_message_size);
loader->corrupted = TRUE; loader->corrupted = TRUE;
return; return;
} }
...@@ -1220,13 +1276,40 @@ _dbus_message_loader_return_buffer (DBusMessageLoader *loader, ...@@ -1220,13 +1276,40 @@ _dbus_message_loader_return_buffer (DBusMessageLoader *loader,
if (message == NULL) if (message == NULL)
break; /* ugh, postpone this I guess. */ break; /* ugh, postpone this I guess. */
if (!_dbus_list_append (&loader->messages, message))
{
dbus_message_unref (message);
break;
}
_dbus_string_copy (&loader->data, header_len, &message->body, 0); _dbus_assert (_dbus_string_get_length (&message->header) == 0);
_dbus_message_set_client_serial (message, client_serial); _dbus_assert (_dbus_string_get_length (&message->body) == 0);
_dbus_list_append (&loader->messages, message); if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
_dbus_string_delete (&loader->data, 0, header_len + body_len); {
_dbus_list_remove_last (&loader->messages, message);
dbus_message_unref (message);
break;
}
if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
{
dbus_bool_t result;
/* put the header back, we'll try again later */
result = _dbus_string_copy_len (&message->header, 0, header_len,
&loader->data, 0);
_dbus_assert (result); /* because DBusString never reallocs smaller */
_dbus_list_remove_last (&loader->messages, message);
dbus_message_unref (message);
break;
}
_dbus_assert (_dbus_string_get_length (&message->header) == header_len);
_dbus_assert (_dbus_string_get_length (&message->body) == body_len);
_dbus_verbose ("Loaded message %p\n", message); _dbus_verbose ("Loaded message %p\n", message);
} }
else else
...@@ -1264,6 +1347,31 @@ _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader) ...@@ -1264,6 +1347,31 @@ _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
return loader->corrupted; return loader->corrupted;
} }
/**
* Sets the maximum size message we allow.
*
* @param loader the loader
* @param size the max message size in bytes
*/
void
_dbus_message_loader_set_max_message_size (DBusMessageLoader *loader,
long size)
{
loader->max_message_size = size;
}
/**
* Gets the maximum allowed message size in bytes.
*
* @param loader the loader
* @returns max size in bytes
*/
long
_dbus_message_loader_get_max_message_size (DBusMessageLoader *loader)
{
return loader->max_message_size;
}
/** @} */ /** @} */
#ifdef DBUS_BUILD_TESTS #ifdef DBUS_BUILD_TESTS
#include "dbus-test.h" #include "dbus-test.h"
......
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-resources.c Resource tracking/limits
*
* Copyright (C) 2003 Red Hat Inc.
*
* Licensed under the Academic Free License version 1.2
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <dbus/dbus-resources.h>
#include <dbus/dbus-internals.h>
/**
* @defgroup DBusResources Resource limits related code
* @ingroup DBusInternals
* @brief DBusCounter and other stuff related to resource limits
*
* Types and functions related to tracking resource limits,
* such as the maximum amount of memory a connection can use
* for messages, etc.
*/
/**
* @defgroup DBusResourcesInternals Resource limits implementation details
* @ingroup DBusInternals
* @brief Resource limits implementation details
*
* Implementation details of resource limits code.
*
* @{
*/
/**
* @brief Internals of DBusCounter.
*
* DBusCounter internals. DBusCounter is an opaque object, it must be
* used via accessor functions.
*/
struct DBusCounter
{
int refcount; /**< reference count */
long value; /**< current counter value */
long notify_guard_value; /**< call notify function when crossing this value */
DBusCounterNotifyFunction notify_function; /**< notify function */
void *notify_data; /**< data for notify function */
};
/** @} */ /* end of resource limits internals docs */
/**
* @addtogroup DBusResources
* @{
*/
/**
* Creates a new DBusCounter. DBusCounter is used
* to count usage of some resource such as memory.
*
* @returns new counter or #NULL on failure
*/
DBusCounter*
_dbus_counter_new (void)
{
DBusCounter *counter;
counter = dbus_new (DBusCounter, 1);
if (counter == NULL)
return NULL;
counter->refcount = 1;
counter->value = 0;
counter->notify_guard_value = 0;
counter->notify_function = NULL;
counter->notify_data = NULL;
return counter;
}
/**
* Increments refcount of the counter
*
* @param counter the counter
*/
void
_dbus_counter_ref (DBusCounter *counter)
{
_dbus_assert (counter->refcount > 0);
counter->refcount += 1;
}
/**
* Decrements refcount of the counter and possibly
* finalizes the counter.
*
* @param counter the counter
*/
void
_dbus_counter_unref (DBusCounter *counter)
{
_dbus_assert (counter->refcount > 0);
counter->refcount -= 1;
if (counter->refcount == 0)
{
dbus_free (counter);
}
}
/**
* Adjusts the value of the counter by the given
* delta which may be positive or negative.
* Calls the notify function from _dbus_counter_set_notify()
* if that function has been specified.
*
* @param counter the counter
* @param delta value to add to the counter's current value
*/
void
_dbus_counter_adjust (DBusCounter *counter,
long delta)
{
long old = counter->value;
counter->value += delta;
#if 0
_dbus_verbose ("Adjusting counter %ld by %ld = %ld\n",
old, delta, counter->value);
#endif
if (counter->notify_function != NULL &&
((old < counter->notify_guard_value &&
counter->value >= counter->notify_guard_value) ||
(old >= counter->notify_guard_value &&
counter->value < counter->notify_guard_value)))
(* counter->notify_function) (counter, counter->notify_data);
}
/**
* Gets the current value of the counter.
*
* @param counter the counter
* @returns its current value
*/
long
_dbus_counter_get_value (DBusCounter *counter)
{
return counter->value;
}
/**
* Sets the notify function for this counter; the notify function is
* called whenever the counter's value crosses the guard value in
* either direction (moving up, or moving down).
*
* @param counter the counter
* @param guard_value the value we're notified if the counter crosses
* @param function function to call in order to notify
* @param user_data data to pass to the function
*/
void
_dbus_counter_set_notify (DBusCounter *counter,
long guard_value,
DBusCounterNotifyFunction function,
void *user_data)
{
counter->notify_guard_value = guard_value;
counter->notify_function = function;
counter->notify_data = user_data;
}
/** @} */ /* end of resource limits exported API */
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-resources.h Resource tracking/limits
*
* Copyright (C) 2003 Red Hat Inc.
*
* Licensed under the Academic Free License version 1.2
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef DBUS_RESOURCES_H
#define DBUS_RESOURCES_H
#include <dbus/dbus-macros.h>
#include <dbus/dbus-errors.h>
#include <dbus/dbus-connection.h>
DBUS_BEGIN_DECLS;
typedef struct DBusCounter DBusCounter;