Logo Search packages:      
Sourcecode: libnih version File versions  Download package

test_output_proxy_standard.c

/* test
 *
 * test.c - auto-generated D-Bus bindings
 *
 * Copyright (C) 2009 Joe Bloggs.
 *
 * This file was automatically generated; see the source for copying
 * conditions.
 */

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */


#include <dbus/dbus.h>

#include <stdint.h>
#include <string.h>

#include <nih/macros.h>
#include <nih/alloc.h>
#include <nih/string.h>
#include <nih/logging.h>
#include <nih/error.h>

#include <nih-dbus/dbus_error.h>
#include <nih-dbus/dbus_message.h>
#include <nih-dbus/dbus_pending_data.h>
#include <nih-dbus/dbus_proxy.h>
#include <nih-dbus/errors.h>

#include "test.h"


/* Prototypes for static functions */
static void              my_com_netsplit_Nih_Test_Poke_notify           (DBusPendingCall *pending_call, NihDBusPendingData *pending_data);
static void              my_com_netsplit_Nih_Test_Peek_notify           (DBusPendingCall *pending_call, NihDBusPendingData *pending_data);
static void              my_com_netsplit_Nih_Test_IsValidAddress_notify (DBusPendingCall *pending_call, NihDBusPendingData *pending_data);
static DBusHandlerResult my_com_netsplit_Nih_Test_Bounce_signal         (DBusConnection *connection, DBusMessage *signal, NihDBusProxySignal *proxied);
static DBusHandlerResult my_com_netsplit_Nih_Test_Exploded_signal       (DBusConnection *connection, DBusMessage *signal, NihDBusProxySignal *proxied);
static void              my_com_netsplit_Nih_Test_colour_get_notify     (DBusPendingCall *pending_call, NihDBusPendingData *pending_data);
static void              my_com_netsplit_Nih_Test_colour_set_notify     (DBusPendingCall *pending_call, NihDBusPendingData *pending_data);
static void              my_com_netsplit_Nih_Test_size_get_notify       (DBusPendingCall *pending_call, NihDBusPendingData *pending_data);
static void              my_com_netsplit_Nih_Test_touch_set_notify      (DBusPendingCall *pending_call, NihDBusPendingData *pending_data);
static void              my_com_netsplit_Nih_Test_get_all_notify        (DBusPendingCall *pending_call, NihDBusPendingData *pending_data);
static void              my_com_netsplit_Nih_Foo_Bing_notify            (DBusPendingCall *pending_call, NihDBusPendingData *pending_data);
static DBusHandlerResult my_com_netsplit_Nih_Foo_NewResult_signal       (DBusConnection *connection, DBusMessage *signal, NihDBusProxySignal *proxied);
static void              my_com_netsplit_Nih_Foo_preferences_get_notify (DBusPendingCall *pending_call, NihDBusPendingData *pending_data);
static void              my_com_netsplit_Nih_Foo_preferences_set_notify (DBusPendingCall *pending_call, NihDBusPendingData *pending_data);
static void              my_com_netsplit_Nih_Foo_get_all_notify         (DBusPendingCall *pending_call, NihDBusPendingData *pending_data);


static const NihDBusArg my_com_netsplit_Nih_Test_Poke_method_args[] = {
      { "address", "u", NIH_DBUS_ARG_IN  },
      { "value",   "s", NIH_DBUS_ARG_IN  },
      { NULL }
};

static const NihDBusArg my_com_netsplit_Nih_Test_Peek_method_args[] = {
      { "address", "u", NIH_DBUS_ARG_IN  },
      { "value",   "s", NIH_DBUS_ARG_OUT },
      { NULL }
};

static const NihDBusArg my_com_netsplit_Nih_Test_IsValidAddress_method_args[] = {
      { "address", "u", NIH_DBUS_ARG_IN  },
      { NULL }
};

static const NihDBusMethod my_com_netsplit_Nih_Test_methods[] = {
      { "Poke",           my_com_netsplit_Nih_Test_Poke_method_args,           NULL },
      { "Peek",           my_com_netsplit_Nih_Test_Peek_method_args,           NULL },
      { "IsValidAddress", my_com_netsplit_Nih_Test_IsValidAddress_method_args, NULL },
      { NULL }
};

static const NihDBusArg my_com_netsplit_Nih_Test_Bounce_signal_args[] = {
      { "height",   "u", NIH_DBUS_ARG_OUT },
      { "velocity", "i", NIH_DBUS_ARG_OUT },
      { NULL }
};

static const NihDBusArg my_com_netsplit_Nih_Test_Exploded_signal_args[] = {
      { NULL }
};

static const NihDBusSignal my_com_netsplit_Nih_Test_signals[] = {
      { "Bounce",   my_com_netsplit_Nih_Test_Bounce_signal_args,   my_com_netsplit_Nih_Test_Bounce_signal   },
      { "Exploded", my_com_netsplit_Nih_Test_Exploded_signal_args, my_com_netsplit_Nih_Test_Exploded_signal },
      { NULL }
};

static const NihDBusProperty my_com_netsplit_Nih_Test_properties[] = {
      { "colour", "s", NIH_DBUS_READWRITE, NULL, NULL },
      { "size",   "u", NIH_DBUS_READ,      NULL, NULL },
      { "touch",  "b", NIH_DBUS_WRITE,     NULL, NULL },
      { NULL }
};

const NihDBusInterface my_com_netsplit_Nih_Test = {
      "com.netsplit.Nih.Test",
      my_com_netsplit_Nih_Test_methods,
      my_com_netsplit_Nih_Test_signals,
      my_com_netsplit_Nih_Test_properties
};

static const NihDBusArg my_com_netsplit_Nih_Foo_Bing_method_args[] = {
      { NULL }
};

static const NihDBusMethod my_com_netsplit_Nih_Foo_methods[] = {
      { "Bing", my_com_netsplit_Nih_Foo_Bing_method_args, NULL },
      { NULL }
};

static const NihDBusArg my_com_netsplit_Nih_Foo_NewResult_signal_args[] = {
      { NULL }
};

static const NihDBusSignal my_com_netsplit_Nih_Foo_signals[] = {
      { "NewResult", my_com_netsplit_Nih_Foo_NewResult_signal_args, my_com_netsplit_Nih_Foo_NewResult_signal },
      { NULL }
};

static const NihDBusProperty my_com_netsplit_Nih_Foo_properties[] = {
      { "preferences", "(us)", NIH_DBUS_READWRITE, NULL, NULL },
      { NULL }
};

const NihDBusInterface my_com_netsplit_Nih_Foo = {
      "com.netsplit.Nih.Foo",
      my_com_netsplit_Nih_Foo_methods,
      my_com_netsplit_Nih_Foo_signals,
      my_com_netsplit_Nih_Foo_properties
};

const NihDBusInterface *my_interfaces[] = {
      &my_com_netsplit_Nih_Test,
      &my_com_netsplit_Nih_Foo,
      NULL
};


DBusPendingCall *
my_test_poke (NihDBusProxy *      proxy,
              uint32_t            address,
              const char *        value,
              MyTestPokeReply     handler,
              NihDBusErrorHandler error_handler,
              void *              data,
              int                 timeout)
{
      DBusMessage *       method_call;
      DBusMessageIter     iter;
      DBusPendingCall *   pending_call;
      NihDBusPendingData *pending_data;

      nih_assert (proxy != NULL);
      nih_assert (value != NULL);
      nih_assert ((handler == NULL) || (error_handler != NULL));

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "com.netsplit.Nih.Test", "Poke");
      if (! method_call)
            nih_return_no_memory_error (NULL);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      /* Marshal a uint32_t onto the message */
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &address)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      /* Marshal a char * onto the message */
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      /* Handle a fire-and-forget message */
      if (! error_handler) {
            dbus_message_set_no_reply (method_call, TRUE);
            if (! dbus_connection_send (proxy->connection, method_call, NULL)) {
                  dbus_message_unref (method_call);
                  nih_return_no_memory_error (NULL);
            }

            dbus_message_unref (method_call);
            return (DBusPendingCall *)TRUE;
      }

      /* Send the message and set up the reply notification. */
      pending_data = nih_dbus_pending_data_new (NULL, proxy->connection,
                                                (NihDBusReplyHandler)handler,
                                                error_handler, data);
      if (! pending_data) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      pending_call = NULL;
      if (! dbus_connection_send_with_reply (proxy->connection, method_call,
                                             &pending_call, timeout)) {
            dbus_message_unref (method_call);
            nih_free (pending_data);
            nih_return_no_memory_error (NULL);
      }

      dbus_message_unref (method_call);

      if (! pending_call) {
            nih_dbus_error_raise (DBUS_ERROR_DISCONNECTED,
                                  "Connection is closed");
            nih_free (pending_data);
            return NULL;
      }

      NIH_MUST (dbus_pending_call_set_notify (pending_call, (DBusPendingCallNotifyFunction)my_com_netsplit_Nih_Test_Poke_notify,
                                              pending_data, (DBusFreeFunction)nih_discard));

      return pending_call;
}

static void
my_com_netsplit_Nih_Test_Poke_notify (DBusPendingCall *   pending_call,
                                      NihDBusPendingData *pending_data)
{
      DBusMessage *   reply;
      DBusMessageIter iter;
      NihDBusMessage *message;
      DBusError       error;

      nih_assert (pending_call != NULL);
      nih_assert (pending_data != NULL);

      nih_assert (dbus_pending_call_get_completed (pending_call));

      /* Steal the reply from the pending call. */
      reply = dbus_pending_call_steal_reply (pending_call);
      nih_assert (reply != NULL);

      /* Handle error replies */
      if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) {
            message = NIH_MUST (nih_dbus_message_new (pending_data, pending_data->connection, reply));

            dbus_error_init (&error);
            dbus_set_error_from_message (&error, message->message);

            nih_error_push_context ();
            nih_dbus_error_raise (error.name, error.message);
            pending_data->error_handler (pending_data->data, message);
            nih_error_pop_context ();

            dbus_error_free (&error);
            nih_free (message);
            dbus_message_unref (reply);
            return;
      }

      nih_assert (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN);

      do {
            __label__ enomem;

            /* Create a message context for the reply, and iterate
             * over its arguments.
             */
            message = nih_dbus_message_new (pending_data, pending_data->connection, reply);
            if (! message)
                  goto enomem;

            dbus_message_iter_init (message->message, &iter);

            if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

      enomem: __attribute__ ((unused));
      } while (! message);

      /* Call the handler function */
      if (pending_data->handler) {
            nih_error_push_context ();
            ((MyTestPokeReply)pending_data->handler) (pending_data->data, message);
            nih_error_pop_context ();
      }

      nih_free (message);
      dbus_message_unref (reply);
}

int
my_test_poke_sync (const void *  parent,
                   NihDBusProxy *proxy,
                   uint32_t      address,
                   const char *  value)
{
      DBusMessage *   method_call;
      DBusMessageIter iter;
      DBusError       error;
      DBusMessage *   reply;

      nih_assert (proxy != NULL);
      nih_assert (value != NULL);

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "com.netsplit.Nih.Test", "Poke");
      if (! method_call)
            nih_return_no_memory_error (-1);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      /* Marshal a uint32_t onto the message */
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &address)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      /* Marshal a char * onto the message */
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      /* Send the message, and wait for the reply. */
      dbus_error_init (&error);

      reply = dbus_connection_send_with_reply_and_block (proxy->connection, method_call, -1, &error);
      if (! reply) {
            dbus_message_unref (method_call);

            if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) {
                  nih_error_raise_no_memory ();
            } else {
                  nih_dbus_error_raise (error.name, error.message);
            }

            dbus_error_free (&error);
            return -1;
      }

      dbus_message_unref (method_call);

      /* Iterate the arguments of the reply */
      dbus_message_iter_init (reply, &iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
            dbus_message_unref (reply);
            nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                              _(NIH_DBUS_INVALID_ARGS_STR));
      }

      dbus_message_unref (reply);

      return 0;
}


DBusPendingCall *
my_test_peek (NihDBusProxy *      proxy,
              uint32_t            address,
              MyTestPeekReply     handler,
              NihDBusErrorHandler error_handler,
              void *              data,
              int                 timeout)
{
      DBusMessage *       method_call;
      DBusMessageIter     iter;
      DBusPendingCall *   pending_call;
      NihDBusPendingData *pending_data;

      nih_assert (proxy != NULL);
      nih_assert ((handler == NULL) || (error_handler != NULL));

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "com.netsplit.Nih.Test", "Peek");
      if (! method_call)
            nih_return_no_memory_error (NULL);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      /* Marshal a uint32_t onto the message */
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &address)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      /* Handle a fire-and-forget message */
      if (! error_handler) {
            dbus_message_set_no_reply (method_call, TRUE);
            if (! dbus_connection_send (proxy->connection, method_call, NULL)) {
                  dbus_message_unref (method_call);
                  nih_return_no_memory_error (NULL);
            }

            dbus_message_unref (method_call);
            return (DBusPendingCall *)TRUE;
      }

      /* Send the message and set up the reply notification. */
      pending_data = nih_dbus_pending_data_new (NULL, proxy->connection,
                                                (NihDBusReplyHandler)handler,
                                                error_handler, data);
      if (! pending_data) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      pending_call = NULL;
      if (! dbus_connection_send_with_reply (proxy->connection, method_call,
                                             &pending_call, timeout)) {
            dbus_message_unref (method_call);
            nih_free (pending_data);
            nih_return_no_memory_error (NULL);
      }

      dbus_message_unref (method_call);

      if (! pending_call) {
            nih_dbus_error_raise (DBUS_ERROR_DISCONNECTED,
                                  "Connection is closed");
            nih_free (pending_data);
            return NULL;
      }

      NIH_MUST (dbus_pending_call_set_notify (pending_call, (DBusPendingCallNotifyFunction)my_com_netsplit_Nih_Test_Peek_notify,
                                              pending_data, (DBusFreeFunction)nih_discard));

      return pending_call;
}

static void
my_com_netsplit_Nih_Test_Peek_notify (DBusPendingCall *   pending_call,
                                      NihDBusPendingData *pending_data)
{
      DBusMessage *   reply;
      DBusMessageIter iter;
      NihDBusMessage *message;
      DBusError       error;
      char *          value;
      const char *    value_dbus;

      nih_assert (pending_call != NULL);
      nih_assert (pending_data != NULL);

      nih_assert (dbus_pending_call_get_completed (pending_call));

      /* Steal the reply from the pending call. */
      reply = dbus_pending_call_steal_reply (pending_call);
      nih_assert (reply != NULL);

      /* Handle error replies */
      if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) {
            message = NIH_MUST (nih_dbus_message_new (pending_data, pending_data->connection, reply));

            dbus_error_init (&error);
            dbus_set_error_from_message (&error, message->message);

            nih_error_push_context ();
            nih_dbus_error_raise (error.name, error.message);
            pending_data->error_handler (pending_data->data, message);
            nih_error_pop_context ();

            dbus_error_free (&error);
            nih_free (message);
            dbus_message_unref (reply);
            return;
      }

      nih_assert (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN);

      do {
            __label__ enomem;

            /* Create a message context for the reply, and iterate
             * over its arguments.
             */
            message = nih_dbus_message_new (pending_data, pending_data->connection, reply);
            if (! message)
                  goto enomem;

            dbus_message_iter_init (message->message, &iter);

            /* Demarshal a char * from the message */
            if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING) {
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

            dbus_message_iter_get_basic (&iter, &value_dbus);

            value = nih_strdup (message, value_dbus);
            if (! value) {
                  nih_free (message);
                  message = NULL;
                  goto enomem;
            }

            dbus_message_iter_next (&iter);

            if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

      enomem: __attribute__ ((unused));
      } while (! message);

      /* Call the handler function */
      if (pending_data->handler) {
            nih_error_push_context ();
            ((MyTestPeekReply)pending_data->handler) (pending_data->data, message, value);
            nih_error_pop_context ();
      }

      nih_free (message);
      dbus_message_unref (reply);
}

int
my_test_peek_sync (const void *  parent,
                   NihDBusProxy *proxy,
                   uint32_t      address,
                   char **       value)
{
      DBusMessage *   method_call;
      DBusMessageIter iter;
      DBusError       error;
      DBusMessage *   reply;
      char *          value_local;
      const char *    value_local_dbus;

      nih_assert (proxy != NULL);
      nih_assert (value != NULL);

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "com.netsplit.Nih.Test", "Peek");
      if (! method_call)
            nih_return_no_memory_error (-1);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      /* Marshal a uint32_t onto the message */
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &address)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      /* Send the message, and wait for the reply. */
      dbus_error_init (&error);

      reply = dbus_connection_send_with_reply_and_block (proxy->connection, method_call, -1, &error);
      if (! reply) {
            dbus_message_unref (method_call);

            if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) {
                  nih_error_raise_no_memory ();
            } else {
                  nih_dbus_error_raise (error.name, error.message);
            }

            dbus_error_free (&error);
            return -1;
      }

      dbus_message_unref (method_call);

      /* Iterate the arguments of the reply */
      dbus_message_iter_init (reply, &iter);

      do {
            __label__ enomem;

            /* Demarshal a char * from the message */
            if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING) {
                  dbus_message_unref (reply);
                  nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                                    _(NIH_DBUS_INVALID_ARGS_STR));
            }

            dbus_message_iter_get_basic (&iter, &value_local_dbus);

            value_local = nih_strdup (parent, value_local_dbus);
            if (! value_local) {
                  *value = NULL;
                  goto enomem;
            }

            dbus_message_iter_next (&iter);

            *value = value_local;
      enomem: __attribute__ ((unused));
      } while (! *value);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
            nih_free (value_local);
            *value = NULL;
            dbus_message_unref (reply);
            nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                              _(NIH_DBUS_INVALID_ARGS_STR));
      }

      dbus_message_unref (reply);

      return 0;
}


DBusPendingCall *
my_test_is_valid_address (NihDBusProxy *            proxy,
                          uint32_t                  address,
                          MyTestIsValidAddressReply handler,
                          NihDBusErrorHandler       error_handler,
                          void *                    data,
                          int                       timeout)
{
      DBusMessage *       method_call;
      DBusMessageIter     iter;
      DBusPendingCall *   pending_call;
      NihDBusPendingData *pending_data;

      nih_assert (proxy != NULL);
      nih_assert ((handler == NULL) || (error_handler != NULL));

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "com.netsplit.Nih.Test", "IsValidAddress");
      if (! method_call)
            nih_return_no_memory_error (NULL);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      /* Marshal a uint32_t onto the message */
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &address)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      /* Handle a fire-and-forget message */
      if (! error_handler) {
            dbus_message_set_no_reply (method_call, TRUE);
            if (! dbus_connection_send (proxy->connection, method_call, NULL)) {
                  dbus_message_unref (method_call);
                  nih_return_no_memory_error (NULL);
            }

            dbus_message_unref (method_call);
            return (DBusPendingCall *)TRUE;
      }

      /* Send the message and set up the reply notification. */
      pending_data = nih_dbus_pending_data_new (NULL, proxy->connection,
                                                (NihDBusReplyHandler)handler,
                                                error_handler, data);
      if (! pending_data) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      pending_call = NULL;
      if (! dbus_connection_send_with_reply (proxy->connection, method_call,
                                             &pending_call, timeout)) {
            dbus_message_unref (method_call);
            nih_free (pending_data);
            nih_return_no_memory_error (NULL);
      }

      dbus_message_unref (method_call);

      if (! pending_call) {
            nih_dbus_error_raise (DBUS_ERROR_DISCONNECTED,
                                  "Connection is closed");
            nih_free (pending_data);
            return NULL;
      }

      NIH_MUST (dbus_pending_call_set_notify (pending_call, (DBusPendingCallNotifyFunction)my_com_netsplit_Nih_Test_IsValidAddress_notify,
                                              pending_data, (DBusFreeFunction)nih_discard));

      return pending_call;
}

static void
my_com_netsplit_Nih_Test_IsValidAddress_notify (DBusPendingCall *   pending_call,
                                                NihDBusPendingData *pending_data)
{
      DBusMessage *   reply;
      DBusMessageIter iter;
      NihDBusMessage *message;
      DBusError       error;

      nih_assert (pending_call != NULL);
      nih_assert (pending_data != NULL);

      nih_assert (dbus_pending_call_get_completed (pending_call));

      /* Steal the reply from the pending call. */
      reply = dbus_pending_call_steal_reply (pending_call);
      nih_assert (reply != NULL);

      /* Handle error replies */
      if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) {
            message = NIH_MUST (nih_dbus_message_new (pending_data, pending_data->connection, reply));

            dbus_error_init (&error);
            dbus_set_error_from_message (&error, message->message);

            nih_error_push_context ();
            nih_dbus_error_raise (error.name, error.message);
            pending_data->error_handler (pending_data->data, message);
            nih_error_pop_context ();

            dbus_error_free (&error);
            nih_free (message);
            dbus_message_unref (reply);
            return;
      }

      nih_assert (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN);

      do {
            __label__ enomem;

            /* Create a message context for the reply, and iterate
             * over its arguments.
             */
            message = nih_dbus_message_new (pending_data, pending_data->connection, reply);
            if (! message)
                  goto enomem;

            dbus_message_iter_init (message->message, &iter);

            if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

      enomem: __attribute__ ((unused));
      } while (! message);

      /* Call the handler function */
      if (pending_data->handler) {
            nih_error_push_context ();
            ((MyTestIsValidAddressReply)pending_data->handler) (pending_data->data, message);
            nih_error_pop_context ();
      }

      nih_free (message);
      dbus_message_unref (reply);
}

int
my_test_is_valid_address_sync (const void *  parent,
                               NihDBusProxy *proxy,
                               uint32_t      address)
{
      DBusMessage *   method_call;
      DBusMessageIter iter;
      DBusError       error;
      DBusMessage *   reply;

      nih_assert (proxy != NULL);

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "com.netsplit.Nih.Test", "IsValidAddress");
      if (! method_call)
            nih_return_no_memory_error (-1);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      /* Marshal a uint32_t onto the message */
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &address)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      /* Send the message, and wait for the reply. */
      dbus_error_init (&error);

      reply = dbus_connection_send_with_reply_and_block (proxy->connection, method_call, -1, &error);
      if (! reply) {
            dbus_message_unref (method_call);

            if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) {
                  nih_error_raise_no_memory ();
            } else {
                  nih_dbus_error_raise (error.name, error.message);
            }

            dbus_error_free (&error);
            return -1;
      }

      dbus_message_unref (method_call);

      /* Iterate the arguments of the reply */
      dbus_message_iter_init (reply, &iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
            dbus_message_unref (reply);
            nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                              _(NIH_DBUS_INVALID_ARGS_STR));
      }

      dbus_message_unref (reply);

      return 0;
}


static DBusHandlerResult
my_com_netsplit_Nih_Test_Bounce_signal (DBusConnection *    connection,
                                        DBusMessage *       signal,
                                        NihDBusProxySignal *proxied)
{
      DBusMessageIter iter;
      NihDBusMessage *message;
      uint32_t        height;
      int32_t         velocity;

      nih_assert (connection != NULL);
      nih_assert (signal != NULL);
      nih_assert (proxied != NULL);
      nih_assert (connection == proxied->proxy->connection);

      if (! dbus_message_is_signal (signal, proxied->interface->name, proxied->signal->name))
            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

      if (! dbus_message_has_path (signal, proxied->proxy->path))
            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

      if (proxied->proxy->name)
            if (! dbus_message_has_sender (signal, proxied->proxy->owner))
                  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

      message = nih_dbus_message_new (NULL, connection, signal);
      if (! message)
            return DBUS_HANDLER_RESULT_NEED_MEMORY;

      /* Iterate the arguments to the signal and demarshal into arguments
       * for our own function call.
       */
      dbus_message_iter_init (message->message, &iter);

      /* Demarshal a uint32_t from the message */
      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32) {
            nih_free (message);
            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
      }

      dbus_message_iter_get_basic (&iter, &height);

      dbus_message_iter_next (&iter);

      /* Demarshal a int32_t from the message */
      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INT32) {
            nih_free (message);
            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
      }

      dbus_message_iter_get_basic (&iter, &velocity);

      dbus_message_iter_next (&iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
            nih_free (message);
            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
      }

      /* Call the handler function */
      nih_error_push_context ();
      ((MyTestBounceHandler)proxied->handler) (proxied->data, message, height, velocity);
      nih_error_pop_context ();
      nih_free (message);

      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}


static DBusHandlerResult
my_com_netsplit_Nih_Test_Exploded_signal (DBusConnection *    connection,
                                          DBusMessage *       signal,
                                          NihDBusProxySignal *proxied)
{
      DBusMessageIter iter;
      NihDBusMessage *message;

      nih_assert (connection != NULL);
      nih_assert (signal != NULL);
      nih_assert (proxied != NULL);
      nih_assert (connection == proxied->proxy->connection);

      if (! dbus_message_is_signal (signal, proxied->interface->name, proxied->signal->name))
            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

      if (! dbus_message_has_path (signal, proxied->proxy->path))
            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

      if (proxied->proxy->name)
            if (! dbus_message_has_sender (signal, proxied->proxy->owner))
                  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

      message = nih_dbus_message_new (NULL, connection, signal);
      if (! message)
            return DBUS_HANDLER_RESULT_NEED_MEMORY;

      /* Iterate the arguments to the signal and demarshal into arguments
       * for our own function call.
       */
      dbus_message_iter_init (message->message, &iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
            nih_free (message);
            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
      }

      /* Call the handler function */
      nih_error_push_context ();
      ((MyTestExplodedHandler)proxied->handler) (proxied->data, message);
      nih_error_pop_context ();
      nih_free (message);

      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}


DBusPendingCall *
my_test_get_colour (NihDBusProxy *       proxy,
                    MyTestGetColourReply handler,
                    NihDBusErrorHandler  error_handler,
                    void *               data,
                    int                  timeout)
{
      DBusMessage *       method_call;
      DBusMessageIter     iter;
      DBusPendingCall *   pending_call;
      NihDBusPendingData *pending_data;
      const char *        interface;
      const char *        property;

      nih_assert (proxy != NULL);
      nih_assert ((handler != NULL) && (error_handler != NULL));

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "org.freedesktop.DBus.Properties", "Get");
      if (! method_call)
            nih_return_no_memory_error (NULL);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      interface = "com.netsplit.Nih.Test";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      property = "colour";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &property)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      /* Send the message and set up the reply notification. */
      pending_data = nih_dbus_pending_data_new (NULL, proxy->connection,
                                                (NihDBusReplyHandler)handler,
                                                error_handler, data);
      if (! pending_data) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      pending_call = NULL;
      if (! dbus_connection_send_with_reply (proxy->connection, method_call,
                                             &pending_call, timeout)) {
            dbus_message_unref (method_call);
            nih_free (pending_data);
            nih_return_no_memory_error (NULL);
      }

      dbus_message_unref (method_call);

      if (! pending_call) {
            nih_dbus_error_raise (DBUS_ERROR_DISCONNECTED,
                                  "Connection is closed");
            nih_free (pending_data);
            return NULL;
      }

      NIH_MUST (dbus_pending_call_set_notify (pending_call, (DBusPendingCallNotifyFunction)my_com_netsplit_Nih_Test_colour_get_notify,
                                              pending_data, (DBusFreeFunction)nih_discard));

      return pending_call;
}

static void
my_com_netsplit_Nih_Test_colour_get_notify (DBusPendingCall *   pending_call,
                                            NihDBusPendingData *pending_data)
{
      DBusMessage *   reply;
      DBusMessageIter iter;
      DBusMessageIter variter;
      NihDBusMessage *message;
      DBusError       error;
      const char *    value_dbus;
      char *          value;

      nih_assert (pending_call != NULL);
      nih_assert (pending_data != NULL);

      nih_assert (dbus_pending_call_get_completed (pending_call));

      /* Steal the reply from the pending call. */
      reply = dbus_pending_call_steal_reply (pending_call);
      nih_assert (reply != NULL);

      /* Handle error replies */
      if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) {
            message = NIH_MUST (nih_dbus_message_new (pending_data, pending_data->connection, reply));

            dbus_error_init (&error);
            dbus_set_error_from_message (&error, message->message);

            nih_error_push_context ();
            nih_dbus_error_raise (error.name, error.message);
            pending_data->error_handler (pending_data->data, message);
            nih_error_pop_context ();

            dbus_error_free (&error);
            nih_free (message);
            dbus_message_unref (reply);
            return;
      }

      nih_assert (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN);

      do {
            __label__ enomem;

            /* Create a message context for the reply, and iterate
             * over and recurse into the arguments.
             */
            message = nih_dbus_message_new (pending_data, pending_data->connection, reply);
            if (! message)
                  goto enomem;

            dbus_message_iter_init (message->message, &iter);

            if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT) {
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

            dbus_message_iter_recurse (&iter, &variter);

            /* Demarshal a char * from the message */
            if (dbus_message_iter_get_arg_type (&variter) != DBUS_TYPE_STRING) {
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

            dbus_message_iter_get_basic (&variter, &value_dbus);

            value = nih_strdup (message, value_dbus);
            if (! value) {
                  nih_free (message);
                  message = NULL;
                  goto enomem;
            }

            dbus_message_iter_next (&variter);

            dbus_message_iter_next (&iter);

            if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

      enomem: __attribute__ ((unused));
      } while (! message);

      /* Call the handler function */
      nih_error_push_context ();
      ((MyTestGetColourReply)pending_data->handler) (pending_data->data, message, value);
      nih_error_pop_context ();

      nih_free (message);
      dbus_message_unref (reply);
}

int
my_test_get_colour_sync (const void *  parent,
                         NihDBusProxy *proxy,
                         char **       value)
{
      DBusMessage *   method_call;
      DBusMessageIter iter;
      DBusMessageIter variter;
      DBusError       error;
      DBusMessage *   reply;
      const char *    interface;
      const char *    property;
      const char *    local_dbus;
      char *          local;

      nih_assert (proxy != NULL);
      nih_assert (value != NULL);

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "org.freedesktop.DBus.Properties", "Get");
      if (! method_call)
            nih_return_no_memory_error (-1);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      interface = "com.netsplit.Nih.Test";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      property = "colour";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &property)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      /* Send the message, and wait for the reply. */
      dbus_error_init (&error);

      reply = dbus_connection_send_with_reply_and_block (proxy->connection, method_call, -1, &error);
      if (! reply) {
            dbus_message_unref (method_call);

            if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) {
                  nih_error_raise_no_memory ();
            } else {
                  nih_dbus_error_raise (error.name, error.message);
            }

            dbus_error_free (&error);
            return -1;
      }

      dbus_message_unref (method_call);

      /* Iterate the method arguments, recursing into the variant */
      dbus_message_iter_init (reply, &iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT) {
            dbus_message_unref (reply);
            nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                              _(NIH_DBUS_INVALID_ARGS_STR));
      }

      dbus_message_iter_recurse (&iter, &variter);

      dbus_message_iter_next (&iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
            dbus_message_unref (reply);
            nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                              _(NIH_DBUS_INVALID_ARGS_STR));
      }

      do {
            __label__ enomem;

            /* Demarshal a char * from the message */
            if (dbus_message_iter_get_arg_type (&variter) != DBUS_TYPE_STRING) {
                  dbus_message_unref (reply);
                  nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                                    _(NIH_DBUS_INVALID_ARGS_STR));
            }

            dbus_message_iter_get_basic (&variter, &local_dbus);

            local = nih_strdup (parent, local_dbus);
            if (! local) {
                  *value = NULL;
                  goto enomem;
            }

            dbus_message_iter_next (&variter);

            *value = local;
      enomem: __attribute__ ((unused));
      } while (! *value);

      dbus_message_unref (reply);

      return 0;
}

DBusPendingCall *
my_test_set_colour (NihDBusProxy *       proxy,
                    const char *         value,
                    MyTestSetColourReply handler,
                    NihDBusErrorHandler  error_handler,
                    void *               data,
                    int                  timeout)
{
      DBusMessage *       method_call;
      DBusMessageIter     iter;
      DBusMessageIter     variter;
      DBusPendingCall *   pending_call;
      NihDBusPendingData *pending_data;
      const char *        interface;
      const char *        property;

      nih_assert (proxy != NULL);
      nih_assert (value != NULL);
      nih_assert ((handler == NULL) || (error_handler != NULL));

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "org.freedesktop.DBus.Properties", "Set");
      if (! method_call)
            nih_return_no_memory_error (NULL);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      interface = "com.netsplit.Nih.Test";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      property = "colour";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &property)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      if (! dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "s", &variter)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      /* Marshal a char * onto the message */
      if (! dbus_message_iter_append_basic (&variter, DBUS_TYPE_STRING, &value)) {
            dbus_message_iter_abandon_container (&iter, &variter);
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      if (! dbus_message_iter_close_container (&iter, &variter)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      /* Handle a fire-and-forget message */
      if (! error_handler) {
            dbus_message_set_no_reply (method_call, TRUE);
            if (! dbus_connection_send (proxy->connection, method_call, NULL)) {
                  dbus_message_unref (method_call);
                  nih_return_no_memory_error (NULL);
            }

            dbus_message_unref (method_call);
            return (DBusPendingCall *)TRUE;
      }

      /* Send the message and set up the reply notification. */
      pending_data = nih_dbus_pending_data_new (NULL, proxy->connection,
                                                (NihDBusReplyHandler)handler,
                                                error_handler, data);
      if (! pending_data) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      pending_call = NULL;
      if (! dbus_connection_send_with_reply (proxy->connection, method_call,
                                             &pending_call, timeout)) {
            dbus_message_unref (method_call);
            nih_free (pending_data);
            nih_return_no_memory_error (NULL);
      }

      dbus_message_unref (method_call);

      if (! pending_call) {
            nih_dbus_error_raise (DBUS_ERROR_DISCONNECTED,
                                  "Connection is closed");
            nih_free (pending_data);
            return NULL;
      }

      NIH_MUST (dbus_pending_call_set_notify (pending_call, (DBusPendingCallNotifyFunction)my_com_netsplit_Nih_Test_colour_set_notify,
                                              pending_data, (DBusFreeFunction)nih_discard));

      return pending_call;
}

static void
my_com_netsplit_Nih_Test_colour_set_notify (DBusPendingCall *   pending_call,
                                            NihDBusPendingData *pending_data)
{
      DBusMessage *   reply;
      DBusMessageIter iter;
      NihDBusMessage *message;
      DBusError       error;

      nih_assert (pending_call != NULL);
      nih_assert (pending_data != NULL);

      nih_assert (dbus_pending_call_get_completed (pending_call));

      /* Steal the reply from the pending call. */
      reply = dbus_pending_call_steal_reply (pending_call);
      nih_assert (reply != NULL);

      /* Handle error replies */
      if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) {
            message = NIH_MUST (nih_dbus_message_new (pending_data, pending_data->connection, reply));

            dbus_error_init (&error);
            dbus_set_error_from_message (&error, message->message);

            nih_error_push_context ();
            nih_dbus_error_raise (error.name, error.message);
            pending_data->error_handler (pending_data->data, message);
            nih_error_pop_context ();

            dbus_error_free (&error);
            nih_free (message);
            dbus_message_unref (reply);
            return;
      }

      nih_assert (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN);

      /* Create a message context for the reply, and check
       * there are no arguments.
       */
      message = NIH_MUST (nih_dbus_message_new (pending_data, pending_data->connection, reply));
      dbus_message_iter_init (message->message, &iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
            nih_error_push_context ();
            nih_error_raise (NIH_DBUS_INVALID_ARGS,
                             _(NIH_DBUS_INVALID_ARGS_STR));
            pending_data->error_handler (pending_data->data, message);
            nih_error_pop_context ();

            nih_free (message);
            dbus_message_unref (reply);
            return;
      }

      /* Call the handler function */
      if (pending_data->handler) {
            nih_error_push_context ();
            ((MyTestSetColourReply)pending_data->handler) (pending_data->data, message);
            nih_error_pop_context ();
      }

      nih_free (message);
      dbus_message_unref (reply);
}

int
my_test_set_colour_sync (const void *  parent,
                         NihDBusProxy *proxy,
                         const char *  value)
{
      DBusMessage *   method_call;
      DBusMessageIter iter;
      DBusMessageIter variter;
      DBusError       error;
      DBusMessage *   reply;
      const char *    interface;
      const char *    property;

      nih_assert (proxy != NULL);
      nih_assert (value != NULL);

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "org.freedesktop.DBus.Properties", "Set");
      if (! method_call)
            nih_return_no_memory_error (-1);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      interface = "com.netsplit.Nih.Test";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      property = "colour";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &property)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      if (! dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "s", &variter)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      /* Marshal a char * onto the message */
      if (! dbus_message_iter_append_basic (&variter, DBUS_TYPE_STRING, &value)) {
            dbus_message_iter_abandon_container (&iter, &variter);
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      if (! dbus_message_iter_close_container (&iter, &variter)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      /* Send the message, and wait for the reply. */
      dbus_error_init (&error);

      reply = dbus_connection_send_with_reply_and_block (proxy->connection, method_call, -1, &error);
      if (! reply) {
            dbus_message_unref (method_call);

            if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) {
                  nih_error_raise_no_memory ();
            } else {
                  nih_dbus_error_raise (error.name, error.message);
            }

            dbus_error_free (&error);
            return -1;
      }

      /* Check the reply has no arguments */
      dbus_message_unref (method_call);
      dbus_message_iter_init (reply, &iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
            dbus_message_unref (reply);
            nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                              _(NIH_DBUS_INVALID_ARGS_STR));
      }

      dbus_message_unref (reply);

      return 0;
}


DBusPendingCall *
my_test_get_size (NihDBusProxy *      proxy,
                  MyTestGetSizeReply  handler,
                  NihDBusErrorHandler error_handler,
                  void *              data,
                  int                 timeout)
{
      DBusMessage *       method_call;
      DBusMessageIter     iter;
      DBusPendingCall *   pending_call;
      NihDBusPendingData *pending_data;
      const char *        interface;
      const char *        property;

      nih_assert (proxy != NULL);
      nih_assert ((handler != NULL) && (error_handler != NULL));

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "org.freedesktop.DBus.Properties", "Get");
      if (! method_call)
            nih_return_no_memory_error (NULL);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      interface = "com.netsplit.Nih.Test";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      property = "size";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &property)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      /* Send the message and set up the reply notification. */
      pending_data = nih_dbus_pending_data_new (NULL, proxy->connection,
                                                (NihDBusReplyHandler)handler,
                                                error_handler, data);
      if (! pending_data) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      pending_call = NULL;
      if (! dbus_connection_send_with_reply (proxy->connection, method_call,
                                             &pending_call, timeout)) {
            dbus_message_unref (method_call);
            nih_free (pending_data);
            nih_return_no_memory_error (NULL);
      }

      dbus_message_unref (method_call);

      if (! pending_call) {
            nih_dbus_error_raise (DBUS_ERROR_DISCONNECTED,
                                  "Connection is closed");
            nih_free (pending_data);
            return NULL;
      }

      NIH_MUST (dbus_pending_call_set_notify (pending_call, (DBusPendingCallNotifyFunction)my_com_netsplit_Nih_Test_size_get_notify,
                                              pending_data, (DBusFreeFunction)nih_discard));

      return pending_call;
}

static void
my_com_netsplit_Nih_Test_size_get_notify (DBusPendingCall *   pending_call,
                                          NihDBusPendingData *pending_data)
{
      DBusMessage *   reply;
      DBusMessageIter iter;
      DBusMessageIter variter;
      NihDBusMessage *message;
      DBusError       error;
      uint32_t        value;

      nih_assert (pending_call != NULL);
      nih_assert (pending_data != NULL);

      nih_assert (dbus_pending_call_get_completed (pending_call));

      /* Steal the reply from the pending call. */
      reply = dbus_pending_call_steal_reply (pending_call);
      nih_assert (reply != NULL);

      /* Handle error replies */
      if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) {
            message = NIH_MUST (nih_dbus_message_new (pending_data, pending_data->connection, reply));

            dbus_error_init (&error);
            dbus_set_error_from_message (&error, message->message);

            nih_error_push_context ();
            nih_dbus_error_raise (error.name, error.message);
            pending_data->error_handler (pending_data->data, message);
            nih_error_pop_context ();

            dbus_error_free (&error);
            nih_free (message);
            dbus_message_unref (reply);
            return;
      }

      nih_assert (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN);

      do {
            __label__ enomem;

            /* Create a message context for the reply, and iterate
             * over and recurse into the arguments.
             */
            message = nih_dbus_message_new (pending_data, pending_data->connection, reply);
            if (! message)
                  goto enomem;

            dbus_message_iter_init (message->message, &iter);

            if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT) {
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

            dbus_message_iter_recurse (&iter, &variter);

            /* Demarshal a uint32_t from the message */
            if (dbus_message_iter_get_arg_type (&variter) != DBUS_TYPE_UINT32) {
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

            dbus_message_iter_get_basic (&variter, &value);

            dbus_message_iter_next (&variter);

            dbus_message_iter_next (&iter);

            if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

      enomem: __attribute__ ((unused));
      } while (! message);

      /* Call the handler function */
      nih_error_push_context ();
      ((MyTestGetSizeReply)pending_data->handler) (pending_data->data, message, value);
      nih_error_pop_context ();

      nih_free (message);
      dbus_message_unref (reply);
}

int
my_test_get_size_sync (const void *  parent,
                       NihDBusProxy *proxy,
                       uint32_t *    value)
{
      DBusMessage *   method_call;
      DBusMessageIter iter;
      DBusMessageIter variter;
      DBusError       error;
      DBusMessage *   reply;
      const char *    interface;
      const char *    property;
      uint32_t        local;

      nih_assert (proxy != NULL);
      nih_assert (value != NULL);

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "org.freedesktop.DBus.Properties", "Get");
      if (! method_call)
            nih_return_no_memory_error (-1);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      interface = "com.netsplit.Nih.Test";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      property = "size";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &property)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      /* Send the message, and wait for the reply. */
      dbus_error_init (&error);

      reply = dbus_connection_send_with_reply_and_block (proxy->connection, method_call, -1, &error);
      if (! reply) {
            dbus_message_unref (method_call);

            if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) {
                  nih_error_raise_no_memory ();
            } else {
                  nih_dbus_error_raise (error.name, error.message);
            }

            dbus_error_free (&error);
            return -1;
      }

      dbus_message_unref (method_call);

      /* Iterate the method arguments, recursing into the variant */
      dbus_message_iter_init (reply, &iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT) {
            dbus_message_unref (reply);
            nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                              _(NIH_DBUS_INVALID_ARGS_STR));
      }

      dbus_message_iter_recurse (&iter, &variter);

      dbus_message_iter_next (&iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
            dbus_message_unref (reply);
            nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                              _(NIH_DBUS_INVALID_ARGS_STR));
      }

      do {
            __label__ enomem;

            /* Demarshal a uint32_t from the message */
            if (dbus_message_iter_get_arg_type (&variter) != DBUS_TYPE_UINT32) {
                  dbus_message_unref (reply);
                  nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                                    _(NIH_DBUS_INVALID_ARGS_STR));
            }

            dbus_message_iter_get_basic (&variter, &local);

            dbus_message_iter_next (&variter);

            *value = local;
      enomem: __attribute__ ((unused));
      } while (! *value);

      dbus_message_unref (reply);

      return 0;
}


DBusPendingCall *
my_test_set_touch (NihDBusProxy *      proxy,
                   int                 value,
                   MyTestSetTouchReply handler,
                   NihDBusErrorHandler error_handler,
                   void *              data,
                   int                 timeout)
{
      DBusMessage *       method_call;
      DBusMessageIter     iter;
      DBusMessageIter     variter;
      DBusPendingCall *   pending_call;
      NihDBusPendingData *pending_data;
      const char *        interface;
      const char *        property;

      nih_assert (proxy != NULL);
      nih_assert ((handler == NULL) || (error_handler != NULL));

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "org.freedesktop.DBus.Properties", "Set");
      if (! method_call)
            nih_return_no_memory_error (NULL);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      interface = "com.netsplit.Nih.Test";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      property = "touch";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &property)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      if (! dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "b", &variter)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      /* Marshal a int onto the message */
      if (! dbus_message_iter_append_basic (&variter, DBUS_TYPE_BOOLEAN, &value)) {
            dbus_message_iter_abandon_container (&iter, &variter);
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      if (! dbus_message_iter_close_container (&iter, &variter)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      /* Handle a fire-and-forget message */
      if (! error_handler) {
            dbus_message_set_no_reply (method_call, TRUE);
            if (! dbus_connection_send (proxy->connection, method_call, NULL)) {
                  dbus_message_unref (method_call);
                  nih_return_no_memory_error (NULL);
            }

            dbus_message_unref (method_call);
            return (DBusPendingCall *)TRUE;
      }

      /* Send the message and set up the reply notification. */
      pending_data = nih_dbus_pending_data_new (NULL, proxy->connection,
                                                (NihDBusReplyHandler)handler,
                                                error_handler, data);
      if (! pending_data) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      pending_call = NULL;
      if (! dbus_connection_send_with_reply (proxy->connection, method_call,
                                             &pending_call, timeout)) {
            dbus_message_unref (method_call);
            nih_free (pending_data);
            nih_return_no_memory_error (NULL);
      }

      dbus_message_unref (method_call);

      if (! pending_call) {
            nih_dbus_error_raise (DBUS_ERROR_DISCONNECTED,
                                  "Connection is closed");
            nih_free (pending_data);
            return NULL;
      }

      NIH_MUST (dbus_pending_call_set_notify (pending_call, (DBusPendingCallNotifyFunction)my_com_netsplit_Nih_Test_touch_set_notify,
                                              pending_data, (DBusFreeFunction)nih_discard));

      return pending_call;
}

static void
my_com_netsplit_Nih_Test_touch_set_notify (DBusPendingCall *   pending_call,
                                           NihDBusPendingData *pending_data)
{
      DBusMessage *   reply;
      DBusMessageIter iter;
      NihDBusMessage *message;
      DBusError       error;

      nih_assert (pending_call != NULL);
      nih_assert (pending_data != NULL);

      nih_assert (dbus_pending_call_get_completed (pending_call));

      /* Steal the reply from the pending call. */
      reply = dbus_pending_call_steal_reply (pending_call);
      nih_assert (reply != NULL);

      /* Handle error replies */
      if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) {
            message = NIH_MUST (nih_dbus_message_new (pending_data, pending_data->connection, reply));

            dbus_error_init (&error);
            dbus_set_error_from_message (&error, message->message);

            nih_error_push_context ();
            nih_dbus_error_raise (error.name, error.message);
            pending_data->error_handler (pending_data->data, message);
            nih_error_pop_context ();

            dbus_error_free (&error);
            nih_free (message);
            dbus_message_unref (reply);
            return;
      }

      nih_assert (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN);

      /* Create a message context for the reply, and check
       * there are no arguments.
       */
      message = NIH_MUST (nih_dbus_message_new (pending_data, pending_data->connection, reply));
      dbus_message_iter_init (message->message, &iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
            nih_error_push_context ();
            nih_error_raise (NIH_DBUS_INVALID_ARGS,
                             _(NIH_DBUS_INVALID_ARGS_STR));
            pending_data->error_handler (pending_data->data, message);
            nih_error_pop_context ();

            nih_free (message);
            dbus_message_unref (reply);
            return;
      }

      /* Call the handler function */
      if (pending_data->handler) {
            nih_error_push_context ();
            ((MyTestSetTouchReply)pending_data->handler) (pending_data->data, message);
            nih_error_pop_context ();
      }

      nih_free (message);
      dbus_message_unref (reply);
}

int
my_test_set_touch_sync (const void *  parent,
                        NihDBusProxy *proxy,
                        int           value)
{
      DBusMessage *   method_call;
      DBusMessageIter iter;
      DBusMessageIter variter;
      DBusError       error;
      DBusMessage *   reply;
      const char *    interface;
      const char *    property;

      nih_assert (proxy != NULL);

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "org.freedesktop.DBus.Properties", "Set");
      if (! method_call)
            nih_return_no_memory_error (-1);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      interface = "com.netsplit.Nih.Test";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      property = "touch";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &property)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      if (! dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "b", &variter)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      /* Marshal a int onto the message */
      if (! dbus_message_iter_append_basic (&variter, DBUS_TYPE_BOOLEAN, &value)) {
            dbus_message_iter_abandon_container (&iter, &variter);
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      if (! dbus_message_iter_close_container (&iter, &variter)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      /* Send the message, and wait for the reply. */
      dbus_error_init (&error);

      reply = dbus_connection_send_with_reply_and_block (proxy->connection, method_call, -1, &error);
      if (! reply) {
            dbus_message_unref (method_call);

            if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) {
                  nih_error_raise_no_memory ();
            } else {
                  nih_dbus_error_raise (error.name, error.message);
            }

            dbus_error_free (&error);
            return -1;
      }

      /* Check the reply has no arguments */
      dbus_message_unref (method_call);
      dbus_message_iter_init (reply, &iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
            dbus_message_unref (reply);
            nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                              _(NIH_DBUS_INVALID_ARGS_STR));
      }

      dbus_message_unref (reply);

      return 0;
}


DBusPendingCall *
my_test_get_all (NihDBusProxy *      proxy,
                 MyTestGetAllReply   handler,
                 NihDBusErrorHandler error_handler,
                 void *              data,
                 int                 timeout)
{
      DBusMessage *       method_call;
      DBusMessageIter     iter;
      DBusPendingCall *   pending_call;
      NihDBusPendingData *pending_data;
      const char *        interface;

      nih_assert (proxy != NULL);
      nih_assert ((handler != NULL) && (error_handler != NULL));

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "org.freedesktop.DBus.Properties", "GetAll");
      if (! method_call)
            nih_return_no_memory_error (NULL);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      interface = "com.netsplit.Nih.Test";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      /* Send the message and set up the reply notification. */
      pending_data = nih_dbus_pending_data_new (NULL, proxy->connection,
                                                (NihDBusReplyHandler)handler,
                                                error_handler, data);
      if (! pending_data) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      pending_call = NULL;
      if (! dbus_connection_send_with_reply (proxy->connection, method_call,
                                             &pending_call, timeout)) {
            dbus_message_unref (method_call);
            nih_free (pending_data);
            nih_return_no_memory_error (NULL);
      }

      dbus_message_unref (method_call);

      if (! pending_call) {
            nih_dbus_error_raise (DBUS_ERROR_DISCONNECTED,
                                  "Connection is closed");
            nih_free (pending_data);
            return NULL;
      }

      NIH_MUST (dbus_pending_call_set_notify (pending_call, (DBusPendingCallNotifyFunction)my_com_netsplit_Nih_Test_get_all_notify,
                                              pending_data, (DBusFreeFunction)nih_discard));

      return pending_call;
}

static void
my_com_netsplit_Nih_Test_get_all_notify (DBusPendingCall *   pending_call,
                                         NihDBusPendingData *pending_data)
{
      DBusMessage *     reply;
      DBusMessageIter   iter;
      DBusMessageIter   arrayiter;
      DBusMessageIter   dictiter;
      DBusMessageIter   variter;
      NihDBusMessage *  message;
      DBusError         error;
      const char *      property;
      MyTestProperties *properties;
      size_t            property_count;
      char *            colour;
      const char *      colour_dbus;
      uint32_t          size;

      nih_assert (pending_call != NULL);
      nih_assert (pending_data != NULL);

      nih_assert (dbus_pending_call_get_completed (pending_call));

      /* Steal the reply from the pending call. */
      reply = dbus_pending_call_steal_reply (pending_call);
      nih_assert (reply != NULL);

      /* Handle error replies */
      if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) {
            message = NIH_MUST (nih_dbus_message_new (pending_data, pending_data->connection, reply));

            dbus_error_init (&error);
            dbus_set_error_from_message (&error, message->message);

            nih_error_push_context ();
            nih_dbus_error_raise (error.name, error.message);
            pending_data->error_handler (pending_data->data, message);
            nih_error_pop_context ();

            dbus_error_free (&error);
            nih_free (message);
            dbus_message_unref (reply);
            return;
      }

      nih_assert (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN);

      /* Create a message context for the reply, and iterate
       * over and recurse into the arguments.
       */
      message = NIH_MUST (nih_dbus_message_new (pending_data, pending_data->connection, reply));

      /* Iterate the method arguments, recursing into the array */
      dbus_message_iter_init (reply, &iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) {
            nih_error_push_context ();
            nih_error_raise (NIH_DBUS_INVALID_ARGS,
                             _(NIH_DBUS_INVALID_ARGS_STR));
            pending_data->error_handler (pending_data->data, message);
            nih_error_pop_context ();

            nih_free (message);
            dbus_message_unref (reply);
            return;
      }

      properties = NIH_MUST (nih_new (message, MyTestProperties));
      property_count = 0;

      dbus_message_iter_recurse (&iter, &arrayiter);

      while (dbus_message_iter_get_arg_type (&arrayiter) != DBUS_TYPE_INVALID) {
            __label__ enomem;

            if (dbus_message_iter_get_arg_type (&arrayiter) != DBUS_TYPE_DICT_ENTRY) {
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

            dbus_message_iter_recurse (&arrayiter, &dictiter);

            if (dbus_message_iter_get_arg_type (&dictiter) != DBUS_TYPE_STRING) {
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

            dbus_message_iter_get_basic (&dictiter, &property);

            dbus_message_iter_next (&dictiter);

            if (dbus_message_iter_get_arg_type (&dictiter) != DBUS_TYPE_VARIANT) {
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

            dbus_message_iter_recurse (&dictiter, &variter);

            if (! strcmp (property, "colour")) {
                  /* Demarshal a char * from the message */
                  if (dbus_message_iter_get_arg_type (&variter) != DBUS_TYPE_STRING) {
                        nih_error_push_context ();
                        nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                         _(NIH_DBUS_INVALID_ARGS_STR));
                        pending_data->error_handler (pending_data->data, message);
                        nih_error_pop_context ();

                        nih_free (message);
                        dbus_message_unref (reply);
                        return;
                  }

                  dbus_message_iter_get_basic (&variter, &colour_dbus);

                  colour = nih_strdup (properties, colour_dbus);
                  if (! colour) {
                        goto enomem;
                  }

                  dbus_message_iter_next (&variter);

                  properties->colour = colour;

                  nih_assert (++property_count);
            }

            if (! strcmp (property, "size")) {
                  /* Demarshal a uint32_t from the message */
                  if (dbus_message_iter_get_arg_type (&variter) != DBUS_TYPE_UINT32) {
                        nih_error_push_context ();
                        nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                         _(NIH_DBUS_INVALID_ARGS_STR));
                        pending_data->error_handler (pending_data->data, message);
                        nih_error_pop_context ();

                        nih_free (message);
                        dbus_message_unref (reply);
                        return;
                  }

                  dbus_message_iter_get_basic (&variter, &size);

                  dbus_message_iter_next (&variter);

                  properties->size = size;

                  nih_assert (++property_count);
            }

            dbus_message_iter_next (&dictiter);

            if (dbus_message_iter_get_arg_type (&dictiter) != DBUS_TYPE_INVALID) {
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

            dbus_message_iter_next (&arrayiter);
      enomem: __attribute__ ((unused));
      }

      dbus_message_iter_next (&iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
            nih_error_push_context ();
            nih_error_raise (NIH_DBUS_INVALID_ARGS,
                             _(NIH_DBUS_INVALID_ARGS_STR));
            pending_data->error_handler (pending_data->data, message);
            nih_error_pop_context ();

            nih_free (message);
            dbus_message_unref (reply);
            return;
      }

      if (property_count < 2) {
            nih_error_push_context ();
            nih_error_raise (NIH_DBUS_INVALID_ARGS,
                             _(NIH_DBUS_INVALID_ARGS_STR));
            pending_data->error_handler (pending_data->data, message);
            nih_error_pop_context ();

            nih_free (message);
            dbus_message_unref (reply);
            return;
      }

      /* Call the handler function */
      nih_error_push_context ();
      ((MyTestGetAllReply)pending_data->handler) (pending_data->data, message, properties);
      nih_error_pop_context ();

      nih_free (message);
      dbus_message_unref (reply);
}

int
my_test_get_all_sync (const void *       parent,
                      NihDBusProxy *     proxy,
                      MyTestProperties **properties)
{
      DBusMessage *   method_call;
      DBusMessageIter iter;
      DBusMessageIter arrayiter;
      DBusMessageIter dictiter;
      DBusMessageIter variter;
      DBusError       error;
      DBusMessage *   reply;
      size_t          property_count;
      const char *    interface;
      const char *    property;
      char *          colour;
      const char *    colour_dbus;
      uint32_t        size;

      nih_assert (proxy != NULL);
      nih_assert (properties != NULL);

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "org.freedesktop.DBus.Properties", "GetAll");
      if (! method_call)
            nih_return_no_memory_error (-1);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      interface = "com.netsplit.Nih.Test";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      /* Send the message, and wait for the reply. */
      dbus_error_init (&error);

      reply = dbus_connection_send_with_reply_and_block (proxy->connection, method_call, -1, &error);
      if (! reply) {
            dbus_message_unref (method_call);

            if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) {
                  nih_error_raise_no_memory ();
            } else {
                  nih_dbus_error_raise (error.name, error.message);
            }

            dbus_error_free (&error);
            return -1;
      }

      dbus_message_unref (method_call);

      /* Iterate the method arguments, recursing into the array */
      dbus_message_iter_init (reply, &iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) {
            dbus_message_unref (reply);
            nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                              _(NIH_DBUS_INVALID_ARGS_STR));
      }

      *properties = NIH_MUST (nih_new (parent, MyTestProperties));
      property_count = 0;

      dbus_message_iter_recurse (&iter, &arrayiter);

      while (dbus_message_iter_get_arg_type (&arrayiter) != DBUS_TYPE_INVALID) {
            __label__ enomem;

            if (dbus_message_iter_get_arg_type (&arrayiter) != DBUS_TYPE_DICT_ENTRY) {
                  nih_free (*properties);
                  *properties = NULL;
                  dbus_message_unref (reply);
                  nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                                    _(NIH_DBUS_INVALID_ARGS_STR));
            }

            dbus_message_iter_recurse (&arrayiter, &dictiter);

            if (dbus_message_iter_get_arg_type (&dictiter) != DBUS_TYPE_STRING) {
                  nih_free (*properties);
                  *properties = NULL;
                  dbus_message_unref (reply);
                  nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                                    _(NIH_DBUS_INVALID_ARGS_STR));
            }

            dbus_message_iter_get_basic (&dictiter, &property);

            dbus_message_iter_next (&dictiter);

            if (dbus_message_iter_get_arg_type (&dictiter) != DBUS_TYPE_VARIANT) {
                  nih_free (*properties);
                  *properties = NULL;
                  dbus_message_unref (reply);
                  nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                                    _(NIH_DBUS_INVALID_ARGS_STR));
            }

            dbus_message_iter_recurse (&dictiter, &variter);

            if (! strcmp (property, "colour")) {
                  /* Demarshal a char * from the message */
                  if (dbus_message_iter_get_arg_type (&variter) != DBUS_TYPE_STRING) {
                        nih_free (*properties);
                        *properties = NULL;
                        dbus_message_unref (reply);
                        nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                                          _(NIH_DBUS_INVALID_ARGS_STR));
                  }

                  dbus_message_iter_get_basic (&variter, &colour_dbus);

                  colour = nih_strdup (*properties, colour_dbus);
                  if (! colour) {
                        goto enomem;
                  }

                  dbus_message_iter_next (&variter);

                  (*properties)->colour = colour;

                  nih_assert (++property_count);
            }

            if (! strcmp (property, "size")) {
                  /* Demarshal a uint32_t from the message */
                  if (dbus_message_iter_get_arg_type (&variter) != DBUS_TYPE_UINT32) {
                        nih_free (*properties);
                        *properties = NULL;
                        dbus_message_unref (reply);
                        nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                                          _(NIH_DBUS_INVALID_ARGS_STR));
                  }

                  dbus_message_iter_get_basic (&variter, &size);

                  dbus_message_iter_next (&variter);

                  (*properties)->size = size;

                  nih_assert (++property_count);
            }

            dbus_message_iter_next (&dictiter);

            if (dbus_message_iter_get_arg_type (&dictiter) != DBUS_TYPE_INVALID) {
                  nih_free (*properties);
                  *properties = NULL;
                  dbus_message_unref (reply);
                  nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                                    _(NIH_DBUS_INVALID_ARGS_STR));
            }

            dbus_message_iter_next (&arrayiter);
      enomem: __attribute__ ((unused));
      }

      dbus_message_iter_next (&iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
            nih_free (*properties);
            *properties = NULL;
            dbus_message_unref (reply);
            nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                              _(NIH_DBUS_INVALID_ARGS_STR));
      }

      if (property_count < 2) {
            nih_free (*properties);
            *properties = NULL;
            dbus_message_unref (reply);
            nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                              _(NIH_DBUS_INVALID_ARGS_STR));
      }

      dbus_message_unref (reply);

      return 0;
}


DBusPendingCall *
my_foo_bing (NihDBusProxy *      proxy,
             MyFooBingReply      handler,
             NihDBusErrorHandler error_handler,
             void *              data,
             int                 timeout)
{
      DBusMessage *       method_call;
      DBusMessageIter     iter;
      DBusPendingCall *   pending_call;
      NihDBusPendingData *pending_data;

      nih_assert (proxy != NULL);
      nih_assert ((handler == NULL) || (error_handler != NULL));

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "com.netsplit.Nih.Foo", "Bing");
      if (! method_call)
            nih_return_no_memory_error (NULL);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      /* Handle a fire-and-forget message */
      if (! error_handler) {
            dbus_message_set_no_reply (method_call, TRUE);
            if (! dbus_connection_send (proxy->connection, method_call, NULL)) {
                  dbus_message_unref (method_call);
                  nih_return_no_memory_error (NULL);
            }

            dbus_message_unref (method_call);
            return (DBusPendingCall *)TRUE;
      }

      /* Send the message and set up the reply notification. */
      pending_data = nih_dbus_pending_data_new (NULL, proxy->connection,
                                                (NihDBusReplyHandler)handler,
                                                error_handler, data);
      if (! pending_data) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      pending_call = NULL;
      if (! dbus_connection_send_with_reply (proxy->connection, method_call,
                                             &pending_call, timeout)) {
            dbus_message_unref (method_call);
            nih_free (pending_data);
            nih_return_no_memory_error (NULL);
      }

      dbus_message_unref (method_call);

      if (! pending_call) {
            nih_dbus_error_raise (DBUS_ERROR_DISCONNECTED,
                                  "Connection is closed");
            nih_free (pending_data);
            return NULL;
      }

      NIH_MUST (dbus_pending_call_set_notify (pending_call, (DBusPendingCallNotifyFunction)my_com_netsplit_Nih_Foo_Bing_notify,
                                              pending_data, (DBusFreeFunction)nih_discard));

      return pending_call;
}

static void
my_com_netsplit_Nih_Foo_Bing_notify (DBusPendingCall *   pending_call,
                                     NihDBusPendingData *pending_data)
{
      DBusMessage *   reply;
      DBusMessageIter iter;
      NihDBusMessage *message;
      DBusError       error;

      nih_assert (pending_call != NULL);
      nih_assert (pending_data != NULL);

      nih_assert (dbus_pending_call_get_completed (pending_call));

      /* Steal the reply from the pending call. */
      reply = dbus_pending_call_steal_reply (pending_call);
      nih_assert (reply != NULL);

      /* Handle error replies */
      if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) {
            message = NIH_MUST (nih_dbus_message_new (pending_data, pending_data->connection, reply));

            dbus_error_init (&error);
            dbus_set_error_from_message (&error, message->message);

            nih_error_push_context ();
            nih_dbus_error_raise (error.name, error.message);
            pending_data->error_handler (pending_data->data, message);
            nih_error_pop_context ();

            dbus_error_free (&error);
            nih_free (message);
            dbus_message_unref (reply);
            return;
      }

      nih_assert (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN);

      do {
            __label__ enomem;

            /* Create a message context for the reply, and iterate
             * over its arguments.
             */
            message = nih_dbus_message_new (pending_data, pending_data->connection, reply);
            if (! message)
                  goto enomem;

            dbus_message_iter_init (message->message, &iter);

            if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

      enomem: __attribute__ ((unused));
      } while (! message);

      /* Call the handler function */
      if (pending_data->handler) {
            nih_error_push_context ();
            ((MyFooBingReply)pending_data->handler) (pending_data->data, message);
            nih_error_pop_context ();
      }

      nih_free (message);
      dbus_message_unref (reply);
}

int
my_foo_bing_sync (const void *  parent,
                  NihDBusProxy *proxy)
{
      DBusMessage *   method_call;
      DBusMessageIter iter;
      DBusError       error;
      DBusMessage *   reply;

      nih_assert (proxy != NULL);

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "com.netsplit.Nih.Foo", "Bing");
      if (! method_call)
            nih_return_no_memory_error (-1);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      /* Send the message, and wait for the reply. */
      dbus_error_init (&error);

      reply = dbus_connection_send_with_reply_and_block (proxy->connection, method_call, -1, &error);
      if (! reply) {
            dbus_message_unref (method_call);

            if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) {
                  nih_error_raise_no_memory ();
            } else {
                  nih_dbus_error_raise (error.name, error.message);
            }

            dbus_error_free (&error);
            return -1;
      }

      dbus_message_unref (method_call);

      /* Iterate the arguments of the reply */
      dbus_message_iter_init (reply, &iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
            dbus_message_unref (reply);
            nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                              _(NIH_DBUS_INVALID_ARGS_STR));
      }

      dbus_message_unref (reply);

      return 0;
}


static DBusHandlerResult
my_com_netsplit_Nih_Foo_NewResult_signal (DBusConnection *    connection,
                                          DBusMessage *       signal,
                                          NihDBusProxySignal *proxied)
{
      DBusMessageIter iter;
      NihDBusMessage *message;

      nih_assert (connection != NULL);
      nih_assert (signal != NULL);
      nih_assert (proxied != NULL);
      nih_assert (connection == proxied->proxy->connection);

      if (! dbus_message_is_signal (signal, proxied->interface->name, proxied->signal->name))
            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

      if (! dbus_message_has_path (signal, proxied->proxy->path))
            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

      if (proxied->proxy->name)
            if (! dbus_message_has_sender (signal, proxied->proxy->owner))
                  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

      message = nih_dbus_message_new (NULL, connection, signal);
      if (! message)
            return DBUS_HANDLER_RESULT_NEED_MEMORY;

      /* Iterate the arguments to the signal and demarshal into arguments
       * for our own function call.
       */
      dbus_message_iter_init (message->message, &iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
            nih_free (message);
            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
      }

      /* Call the handler function */
      nih_error_push_context ();
      ((MyFooNewResultHandler)proxied->handler) (proxied->data, message);
      nih_error_pop_context ();
      nih_free (message);

      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}


DBusPendingCall *
my_foo_get_preferences (NihDBusProxy *           proxy,
                        MyFooGetPreferencesReply handler,
                        NihDBusErrorHandler      error_handler,
                        void *                   data,
                        int                      timeout)
{
      DBusMessage *       method_call;
      DBusMessageIter     iter;
      DBusPendingCall *   pending_call;
      NihDBusPendingData *pending_data;
      const char *        interface;
      const char *        property;

      nih_assert (proxy != NULL);
      nih_assert ((handler != NULL) && (error_handler != NULL));

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "org.freedesktop.DBus.Properties", "Get");
      if (! method_call)
            nih_return_no_memory_error (NULL);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      interface = "com.netsplit.Nih.Foo";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      property = "preferences";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &property)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      /* Send the message and set up the reply notification. */
      pending_data = nih_dbus_pending_data_new (NULL, proxy->connection,
                                                (NihDBusReplyHandler)handler,
                                                error_handler, data);
      if (! pending_data) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      pending_call = NULL;
      if (! dbus_connection_send_with_reply (proxy->connection, method_call,
                                             &pending_call, timeout)) {
            dbus_message_unref (method_call);
            nih_free (pending_data);
            nih_return_no_memory_error (NULL);
      }

      dbus_message_unref (method_call);

      if (! pending_call) {
            nih_dbus_error_raise (DBUS_ERROR_DISCONNECTED,
                                  "Connection is closed");
            nih_free (pending_data);
            return NULL;
      }

      NIH_MUST (dbus_pending_call_set_notify (pending_call, (DBusPendingCallNotifyFunction)my_com_netsplit_Nih_Foo_preferences_get_notify,
                                              pending_data, (DBusFreeFunction)nih_discard));

      return pending_call;
}

static void
my_com_netsplit_Nih_Foo_preferences_get_notify (DBusPendingCall *   pending_call,
                                                NihDBusPendingData *pending_data)
{
      DBusMessage *     reply;
      DBusMessageIter   iter;
      DBusMessageIter   variter;
      NihDBusMessage *  message;
      DBusError         error;
      DBusMessageIter   value_iter;
      uint32_t          value_item0;
      const char *      value_item1_dbus;
      char *            value_item1;
      MyFooPreferences *value;

      nih_assert (pending_call != NULL);
      nih_assert (pending_data != NULL);

      nih_assert (dbus_pending_call_get_completed (pending_call));

      /* Steal the reply from the pending call. */
      reply = dbus_pending_call_steal_reply (pending_call);
      nih_assert (reply != NULL);

      /* Handle error replies */
      if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) {
            message = NIH_MUST (nih_dbus_message_new (pending_data, pending_data->connection, reply));

            dbus_error_init (&error);
            dbus_set_error_from_message (&error, message->message);

            nih_error_push_context ();
            nih_dbus_error_raise (error.name, error.message);
            pending_data->error_handler (pending_data->data, message);
            nih_error_pop_context ();

            dbus_error_free (&error);
            nih_free (message);
            dbus_message_unref (reply);
            return;
      }

      nih_assert (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN);

      do {
            __label__ enomem;

            /* Create a message context for the reply, and iterate
             * over and recurse into the arguments.
             */
            message = nih_dbus_message_new (pending_data, pending_data->connection, reply);
            if (! message)
                  goto enomem;

            dbus_message_iter_init (message->message, &iter);

            if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT) {
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

            dbus_message_iter_recurse (&iter, &variter);

            /* Demarshal a structure from the message */
            if (dbus_message_iter_get_arg_type (&variter) != DBUS_TYPE_STRUCT) {
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

            dbus_message_iter_recurse (&variter, &value_iter);

            value = nih_new (message, MyFooPreferences);
            if (! value) {
                  nih_free (message);
                  message = NULL;
                  goto enomem;
            }

            /* Demarshal a uint32_t from the message */
            if (dbus_message_iter_get_arg_type (&value_iter) != DBUS_TYPE_UINT32) {
                  nih_free (value);
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

            dbus_message_iter_get_basic (&value_iter, &value_item0);

            dbus_message_iter_next (&value_iter);

            value->item0 = value_item0;

            /* Demarshal a char * from the message */
            if (dbus_message_iter_get_arg_type (&value_iter) != DBUS_TYPE_STRING) {
                  nih_free (value);
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

            dbus_message_iter_get_basic (&value_iter, &value_item1_dbus);

            value_item1 = nih_strdup (value, value_item1_dbus);
            if (! value_item1) {
                  nih_free (value);
                  nih_free (message);
                  message = NULL;
                  goto enomem;
            }

            dbus_message_iter_next (&value_iter);

            value->item1 = value_item1;

            if (dbus_message_iter_get_arg_type (&value_iter) != DBUS_TYPE_INVALID) {
                  nih_free (value);
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

            dbus_message_iter_next (&variter);

            dbus_message_iter_next (&iter);

            if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

      enomem: __attribute__ ((unused));
      } while (! message);

      /* Call the handler function */
      nih_error_push_context ();
      ((MyFooGetPreferencesReply)pending_data->handler) (pending_data->data, message, value);
      nih_error_pop_context ();

      nih_free (message);
      dbus_message_unref (reply);
}

int
my_foo_get_preferences_sync (const void *       parent,
                             NihDBusProxy *     proxy,
                             MyFooPreferences **value)
{
      DBusMessage *     method_call;
      DBusMessageIter   iter;
      DBusMessageIter   variter;
      DBusError         error;
      DBusMessage *     reply;
      const char *      interface;
      const char *      property;
      DBusMessageIter   local_iter;
      uint32_t          local_item0;
      const char *      local_item1_dbus;
      char *            local_item1;
      MyFooPreferences *local;

      nih_assert (proxy != NULL);
      nih_assert (value != NULL);

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "org.freedesktop.DBus.Properties", "Get");
      if (! method_call)
            nih_return_no_memory_error (-1);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      interface = "com.netsplit.Nih.Foo";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      property = "preferences";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &property)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      /* Send the message, and wait for the reply. */
      dbus_error_init (&error);

      reply = dbus_connection_send_with_reply_and_block (proxy->connection, method_call, -1, &error);
      if (! reply) {
            dbus_message_unref (method_call);

            if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) {
                  nih_error_raise_no_memory ();
            } else {
                  nih_dbus_error_raise (error.name, error.message);
            }

            dbus_error_free (&error);
            return -1;
      }

      dbus_message_unref (method_call);

      /* Iterate the method arguments, recursing into the variant */
      dbus_message_iter_init (reply, &iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT) {
            dbus_message_unref (reply);
            nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                              _(NIH_DBUS_INVALID_ARGS_STR));
      }

      dbus_message_iter_recurse (&iter, &variter);

      dbus_message_iter_next (&iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
            dbus_message_unref (reply);
            nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                              _(NIH_DBUS_INVALID_ARGS_STR));
      }

      do {
            __label__ enomem;

            /* Demarshal a structure from the message */
            if (dbus_message_iter_get_arg_type (&variter) != DBUS_TYPE_STRUCT) {
                  dbus_message_unref (reply);
                  nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                                    _(NIH_DBUS_INVALID_ARGS_STR));
            }

            dbus_message_iter_recurse (&variter, &local_iter);

            local = nih_new (parent, MyFooPreferences);
            if (! local) {
                  *value = NULL;
                  goto enomem;
            }

            /* Demarshal a uint32_t from the message */
            if (dbus_message_iter_get_arg_type (&local_iter) != DBUS_TYPE_UINT32) {
                  nih_free (local);
                  dbus_message_unref (reply);
                  nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                                    _(NIH_DBUS_INVALID_ARGS_STR));
            }

            dbus_message_iter_get_basic (&local_iter, &local_item0);

            dbus_message_iter_next (&local_iter);

            local->item0 = local_item0;

            /* Demarshal a char * from the message */
            if (dbus_message_iter_get_arg_type (&local_iter) != DBUS_TYPE_STRING) {
                  nih_free (local);
                  dbus_message_unref (reply);
                  nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                                    _(NIH_DBUS_INVALID_ARGS_STR));
            }

            dbus_message_iter_get_basic (&local_iter, &local_item1_dbus);

            local_item1 = nih_strdup (local, local_item1_dbus);
            if (! local_item1) {
                  nih_free (local);
                  *value = NULL;
                  goto enomem;
            }

            dbus_message_iter_next (&local_iter);

            local->item1 = local_item1;

            if (dbus_message_iter_get_arg_type (&local_iter) != DBUS_TYPE_INVALID) {
                  nih_free (local);
                  dbus_message_unref (reply);
                  nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                                    _(NIH_DBUS_INVALID_ARGS_STR));
            }

            dbus_message_iter_next (&variter);

            *value = local;
      enomem: __attribute__ ((unused));
      } while (! *value);

      dbus_message_unref (reply);

      return 0;
}

DBusPendingCall *
my_foo_set_preferences (NihDBusProxy *           proxy,
                        const MyFooPreferences * value,
                        MyFooSetPreferencesReply handler,
                        NihDBusErrorHandler      error_handler,
                        void *                   data,
                        int                      timeout)
{
      DBusMessage *       method_call;
      DBusMessageIter     iter;
      DBusMessageIter     variter;
      DBusPendingCall *   pending_call;
      NihDBusPendingData *pending_data;
      const char *        interface;
      const char *        property;
      DBusMessageIter     value_iter;
      uint32_t            value_item0;
      const char *        value_item1;

      nih_assert (proxy != NULL);
      nih_assert (value != NULL);
      nih_assert ((handler == NULL) || (error_handler != NULL));

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "org.freedesktop.DBus.Properties", "Set");
      if (! method_call)
            nih_return_no_memory_error (NULL);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      interface = "com.netsplit.Nih.Foo";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      property = "preferences";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &property)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      if (! dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "(us)", &variter)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      /* Marshal a structure onto the message */
      if (! dbus_message_iter_open_container (&variter, DBUS_TYPE_STRUCT, NULL, &value_iter)) {
            dbus_message_iter_abandon_container (&iter, &variter);
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      value_item0 = value->item0;

      /* Marshal a uint32_t onto the message */
      if (! dbus_message_iter_append_basic (&value_iter, DBUS_TYPE_UINT32, &value_item0)) {
            dbus_message_iter_abandon_container (&variter, &value_iter);
            dbus_message_iter_abandon_container (&iter, &variter);
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      value_item1 = value->item1;

      /* Marshal a char * onto the message */
      if (! dbus_message_iter_append_basic (&value_iter, DBUS_TYPE_STRING, &value_item1)) {
            dbus_message_iter_abandon_container (&variter, &value_iter);
            dbus_message_iter_abandon_container (&iter, &variter);
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      if (! dbus_message_iter_close_container (&variter, &value_iter)) {
            dbus_message_iter_abandon_container (&iter, &variter);
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      if (! dbus_message_iter_close_container (&iter, &variter)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      /* Handle a fire-and-forget message */
      if (! error_handler) {
            dbus_message_set_no_reply (method_call, TRUE);
            if (! dbus_connection_send (proxy->connection, method_call, NULL)) {
                  dbus_message_unref (method_call);
                  nih_return_no_memory_error (NULL);
            }

            dbus_message_unref (method_call);
            return (DBusPendingCall *)TRUE;
      }

      /* Send the message and set up the reply notification. */
      pending_data = nih_dbus_pending_data_new (NULL, proxy->connection,
                                                (NihDBusReplyHandler)handler,
                                                error_handler, data);
      if (! pending_data) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      pending_call = NULL;
      if (! dbus_connection_send_with_reply (proxy->connection, method_call,
                                             &pending_call, timeout)) {
            dbus_message_unref (method_call);
            nih_free (pending_data);
            nih_return_no_memory_error (NULL);
      }

      dbus_message_unref (method_call);

      if (! pending_call) {
            nih_dbus_error_raise (DBUS_ERROR_DISCONNECTED,
                                  "Connection is closed");
            nih_free (pending_data);
            return NULL;
      }

      NIH_MUST (dbus_pending_call_set_notify (pending_call, (DBusPendingCallNotifyFunction)my_com_netsplit_Nih_Foo_preferences_set_notify,
                                              pending_data, (DBusFreeFunction)nih_discard));

      return pending_call;
}

static void
my_com_netsplit_Nih_Foo_preferences_set_notify (DBusPendingCall *   pending_call,
                                                NihDBusPendingData *pending_data)
{
      DBusMessage *   reply;
      DBusMessageIter iter;
      NihDBusMessage *message;
      DBusError       error;

      nih_assert (pending_call != NULL);
      nih_assert (pending_data != NULL);

      nih_assert (dbus_pending_call_get_completed (pending_call));

      /* Steal the reply from the pending call. */
      reply = dbus_pending_call_steal_reply (pending_call);
      nih_assert (reply != NULL);

      /* Handle error replies */
      if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) {
            message = NIH_MUST (nih_dbus_message_new (pending_data, pending_data->connection, reply));

            dbus_error_init (&error);
            dbus_set_error_from_message (&error, message->message);

            nih_error_push_context ();
            nih_dbus_error_raise (error.name, error.message);
            pending_data->error_handler (pending_data->data, message);
            nih_error_pop_context ();

            dbus_error_free (&error);
            nih_free (message);
            dbus_message_unref (reply);
            return;
      }

      nih_assert (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN);

      /* Create a message context for the reply, and check
       * there are no arguments.
       */
      message = NIH_MUST (nih_dbus_message_new (pending_data, pending_data->connection, reply));
      dbus_message_iter_init (message->message, &iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
            nih_error_push_context ();
            nih_error_raise (NIH_DBUS_INVALID_ARGS,
                             _(NIH_DBUS_INVALID_ARGS_STR));
            pending_data->error_handler (pending_data->data, message);
            nih_error_pop_context ();

            nih_free (message);
            dbus_message_unref (reply);
            return;
      }

      /* Call the handler function */
      if (pending_data->handler) {
            nih_error_push_context ();
            ((MyFooSetPreferencesReply)pending_data->handler) (pending_data->data, message);
            nih_error_pop_context ();
      }

      nih_free (message);
      dbus_message_unref (reply);
}

int
my_foo_set_preferences_sync (const void *            parent,
                             NihDBusProxy *          proxy,
                             const MyFooPreferences *value)
{
      DBusMessage *   method_call;
      DBusMessageIter iter;
      DBusMessageIter variter;
      DBusError       error;
      DBusMessage *   reply;
      const char *    interface;
      const char *    property;
      DBusMessageIter value_iter;
      uint32_t        value_item0;
      const char *    value_item1;

      nih_assert (proxy != NULL);
      nih_assert (value != NULL);

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "org.freedesktop.DBus.Properties", "Set");
      if (! method_call)
            nih_return_no_memory_error (-1);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      interface = "com.netsplit.Nih.Foo";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      property = "preferences";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &property)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      if (! dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "(us)", &variter)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      /* Marshal a structure onto the message */
      if (! dbus_message_iter_open_container (&variter, DBUS_TYPE_STRUCT, NULL, &value_iter)) {
            dbus_message_iter_abandon_container (&iter, &variter);
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      value_item0 = value->item0;

      /* Marshal a uint32_t onto the message */
      if (! dbus_message_iter_append_basic (&value_iter, DBUS_TYPE_UINT32, &value_item0)) {
            dbus_message_iter_abandon_container (&variter, &value_iter);
            dbus_message_iter_abandon_container (&iter, &variter);
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      value_item1 = value->item1;

      /* Marshal a char * onto the message */
      if (! dbus_message_iter_append_basic (&value_iter, DBUS_TYPE_STRING, &value_item1)) {
            dbus_message_iter_abandon_container (&variter, &value_iter);
            dbus_message_iter_abandon_container (&iter, &variter);
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      if (! dbus_message_iter_close_container (&variter, &value_iter)) {
            dbus_message_iter_abandon_container (&iter, &variter);
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      if (! dbus_message_iter_close_container (&iter, &variter)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      /* Send the message, and wait for the reply. */
      dbus_error_init (&error);

      reply = dbus_connection_send_with_reply_and_block (proxy->connection, method_call, -1, &error);
      if (! reply) {
            dbus_message_unref (method_call);

            if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) {
                  nih_error_raise_no_memory ();
            } else {
                  nih_dbus_error_raise (error.name, error.message);
            }

            dbus_error_free (&error);
            return -1;
      }

      /* Check the reply has no arguments */
      dbus_message_unref (method_call);
      dbus_message_iter_init (reply, &iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
            dbus_message_unref (reply);
            nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                              _(NIH_DBUS_INVALID_ARGS_STR));
      }

      dbus_message_unref (reply);

      return 0;
}


DBusPendingCall *
my_foo_get_all (NihDBusProxy *      proxy,
                MyFooGetAllReply    handler,
                NihDBusErrorHandler error_handler,
                void *              data,
                int                 timeout)
{
      DBusMessage *       method_call;
      DBusMessageIter     iter;
      DBusPendingCall *   pending_call;
      NihDBusPendingData *pending_data;
      const char *        interface;

      nih_assert (proxy != NULL);
      nih_assert ((handler != NULL) && (error_handler != NULL));

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "org.freedesktop.DBus.Properties", "GetAll");
      if (! method_call)
            nih_return_no_memory_error (NULL);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      interface = "com.netsplit.Nih.Foo";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      /* Send the message and set up the reply notification. */
      pending_data = nih_dbus_pending_data_new (NULL, proxy->connection,
                                                (NihDBusReplyHandler)handler,
                                                error_handler, data);
      if (! pending_data) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (NULL);
      }

      pending_call = NULL;
      if (! dbus_connection_send_with_reply (proxy->connection, method_call,
                                             &pending_call, timeout)) {
            dbus_message_unref (method_call);
            nih_free (pending_data);
            nih_return_no_memory_error (NULL);
      }

      dbus_message_unref (method_call);

      if (! pending_call) {
            nih_dbus_error_raise (DBUS_ERROR_DISCONNECTED,
                                  "Connection is closed");
            nih_free (pending_data);
            return NULL;
      }

      NIH_MUST (dbus_pending_call_set_notify (pending_call, (DBusPendingCallNotifyFunction)my_com_netsplit_Nih_Foo_get_all_notify,
                                              pending_data, (DBusFreeFunction)nih_discard));

      return pending_call;
}

static void
my_com_netsplit_Nih_Foo_get_all_notify (DBusPendingCall *   pending_call,
                                        NihDBusPendingData *pending_data)
{
      DBusMessage *     reply;
      DBusMessageIter   iter;
      DBusMessageIter   arrayiter;
      DBusMessageIter   dictiter;
      DBusMessageIter   variter;
      NihDBusMessage *  message;
      DBusError         error;
      const char *      property;
      MyFooProperties * properties;
      size_t            property_count;
      MyFooPreferences *preferences;
      DBusMessageIter   preferences_iter;
      uint32_t          preferences_item0;
      const char *      preferences_item1_dbus;
      char *            preferences_item1;

      nih_assert (pending_call != NULL);
      nih_assert (pending_data != NULL);

      nih_assert (dbus_pending_call_get_completed (pending_call));

      /* Steal the reply from the pending call. */
      reply = dbus_pending_call_steal_reply (pending_call);
      nih_assert (reply != NULL);

      /* Handle error replies */
      if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) {
            message = NIH_MUST (nih_dbus_message_new (pending_data, pending_data->connection, reply));

            dbus_error_init (&error);
            dbus_set_error_from_message (&error, message->message);

            nih_error_push_context ();
            nih_dbus_error_raise (error.name, error.message);
            pending_data->error_handler (pending_data->data, message);
            nih_error_pop_context ();

            dbus_error_free (&error);
            nih_free (message);
            dbus_message_unref (reply);
            return;
      }

      nih_assert (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN);

      /* Create a message context for the reply, and iterate
       * over and recurse into the arguments.
       */
      message = NIH_MUST (nih_dbus_message_new (pending_data, pending_data->connection, reply));

      /* Iterate the method arguments, recursing into the array */
      dbus_message_iter_init (reply, &iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) {
            nih_error_push_context ();
            nih_error_raise (NIH_DBUS_INVALID_ARGS,
                             _(NIH_DBUS_INVALID_ARGS_STR));
            pending_data->error_handler (pending_data->data, message);
            nih_error_pop_context ();

            nih_free (message);
            dbus_message_unref (reply);
            return;
      }

      properties = NIH_MUST (nih_new (message, MyFooProperties));
      property_count = 0;

      dbus_message_iter_recurse (&iter, &arrayiter);

      while (dbus_message_iter_get_arg_type (&arrayiter) != DBUS_TYPE_INVALID) {
            __label__ enomem;

            if (dbus_message_iter_get_arg_type (&arrayiter) != DBUS_TYPE_DICT_ENTRY) {
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

            dbus_message_iter_recurse (&arrayiter, &dictiter);

            if (dbus_message_iter_get_arg_type (&dictiter) != DBUS_TYPE_STRING) {
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

            dbus_message_iter_get_basic (&dictiter, &property);

            dbus_message_iter_next (&dictiter);

            if (dbus_message_iter_get_arg_type (&dictiter) != DBUS_TYPE_VARIANT) {
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

            dbus_message_iter_recurse (&dictiter, &variter);

            if (! strcmp (property, "preferences")) {
                  /* Demarshal a structure from the message */
                  if (dbus_message_iter_get_arg_type (&variter) != DBUS_TYPE_STRUCT) {
                        nih_error_push_context ();
                        nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                         _(NIH_DBUS_INVALID_ARGS_STR));
                        pending_data->error_handler (pending_data->data, message);
                        nih_error_pop_context ();

                        nih_free (message);
                        dbus_message_unref (reply);
                        return;
                  }

                  dbus_message_iter_recurse (&variter, &preferences_iter);

                  preferences = nih_new (properties, MyFooPreferences);
                  if (! preferences) {
                        goto enomem;
                  }

                  /* Demarshal a uint32_t from the message */
                  if (dbus_message_iter_get_arg_type (&preferences_iter) != DBUS_TYPE_UINT32) {
                        nih_free (preferences);
                        nih_error_push_context ();
                        nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                         _(NIH_DBUS_INVALID_ARGS_STR));
                        pending_data->error_handler (pending_data->data, message);
                        nih_error_pop_context ();

                        nih_free (message);
                        dbus_message_unref (reply);
                        return;
                  }

                  dbus_message_iter_get_basic (&preferences_iter, &preferences_item0);

                  dbus_message_iter_next (&preferences_iter);

                  preferences->item0 = preferences_item0;

                  /* Demarshal a char * from the message */
                  if (dbus_message_iter_get_arg_type (&preferences_iter) != DBUS_TYPE_STRING) {
                        nih_free (preferences);
                        nih_error_push_context ();
                        nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                         _(NIH_DBUS_INVALID_ARGS_STR));
                        pending_data->error_handler (pending_data->data, message);
                        nih_error_pop_context ();

                        nih_free (message);
                        dbus_message_unref (reply);
                        return;
                  }

                  dbus_message_iter_get_basic (&preferences_iter, &preferences_item1_dbus);

                  preferences_item1 = nih_strdup (preferences, preferences_item1_dbus);
                  if (! preferences_item1) {
                        nih_free (preferences);
                        goto enomem;
                  }

                  dbus_message_iter_next (&preferences_iter);

                  preferences->item1 = preferences_item1;

                  if (dbus_message_iter_get_arg_type (&preferences_iter) != DBUS_TYPE_INVALID) {
                        nih_free (preferences);
                        nih_error_push_context ();
                        nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                         _(NIH_DBUS_INVALID_ARGS_STR));
                        pending_data->error_handler (pending_data->data, message);
                        nih_error_pop_context ();

                        nih_free (message);
                        dbus_message_unref (reply);
                        return;
                  }

                  dbus_message_iter_next (&variter);

                  properties->preferences = preferences;

                  nih_assert (++property_count);
            }

            dbus_message_iter_next (&dictiter);

            if (dbus_message_iter_get_arg_type (&dictiter) != DBUS_TYPE_INVALID) {
                  nih_error_push_context ();
                  nih_error_raise (NIH_DBUS_INVALID_ARGS,
                                   _(NIH_DBUS_INVALID_ARGS_STR));
                  pending_data->error_handler (pending_data->data, message);
                  nih_error_pop_context ();

                  nih_free (message);
                  dbus_message_unref (reply);
                  return;
            }

            dbus_message_iter_next (&arrayiter);
      enomem: __attribute__ ((unused));
      }

      dbus_message_iter_next (&iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
            nih_error_push_context ();
            nih_error_raise (NIH_DBUS_INVALID_ARGS,
                             _(NIH_DBUS_INVALID_ARGS_STR));
            pending_data->error_handler (pending_data->data, message);
            nih_error_pop_context ();

            nih_free (message);
            dbus_message_unref (reply);
            return;
      }

      if (property_count < 1) {
            nih_error_push_context ();
            nih_error_raise (NIH_DBUS_INVALID_ARGS,
                             _(NIH_DBUS_INVALID_ARGS_STR));
            pending_data->error_handler (pending_data->data, message);
            nih_error_pop_context ();

            nih_free (message);
            dbus_message_unref (reply);
            return;
      }

      /* Call the handler function */
      nih_error_push_context ();
      ((MyFooGetAllReply)pending_data->handler) (pending_data->data, message, properties);
      nih_error_pop_context ();

      nih_free (message);
      dbus_message_unref (reply);
}

int
my_foo_get_all_sync (const void *      parent,
                     NihDBusProxy *    proxy,
                     MyFooProperties **properties)
{
      DBusMessage *     method_call;
      DBusMessageIter   iter;
      DBusMessageIter   arrayiter;
      DBusMessageIter   dictiter;
      DBusMessageIter   variter;
      DBusError         error;
      DBusMessage *     reply;
      size_t            property_count;
      const char *      interface;
      const char *      property;
      MyFooPreferences *preferences;
      DBusMessageIter   preferences_iter;
      uint32_t          preferences_item0;
      const char *      preferences_item1_dbus;
      char *            preferences_item1;

      nih_assert (proxy != NULL);
      nih_assert (properties != NULL);

      /* Construct the method call message. */
      method_call = dbus_message_new_method_call (proxy->name, proxy->path, "org.freedesktop.DBus.Properties", "GetAll");
      if (! method_call)
            nih_return_no_memory_error (-1);

      dbus_message_set_auto_start (method_call, proxy->auto_start);

      dbus_message_iter_init_append (method_call, &iter);

      interface = "com.netsplit.Nih.Foo";
      if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface)) {
            dbus_message_unref (method_call);
            nih_return_no_memory_error (-1);
      }

      /* Send the message, and wait for the reply. */
      dbus_error_init (&error);

      reply = dbus_connection_send_with_reply_and_block (proxy->connection, method_call, -1, &error);
      if (! reply) {
            dbus_message_unref (method_call);

            if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) {
                  nih_error_raise_no_memory ();
            } else {
                  nih_dbus_error_raise (error.name, error.message);
            }

            dbus_error_free (&error);
            return -1;
      }

      dbus_message_unref (method_call);

      /* Iterate the method arguments, recursing into the array */
      dbus_message_iter_init (reply, &iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) {
            dbus_message_unref (reply);
            nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                              _(NIH_DBUS_INVALID_ARGS_STR));
      }

      *properties = NIH_MUST (nih_new (parent, MyFooProperties));
      property_count = 0;

      dbus_message_iter_recurse (&iter, &arrayiter);

      while (dbus_message_iter_get_arg_type (&arrayiter) != DBUS_TYPE_INVALID) {
            __label__ enomem;

            if (dbus_message_iter_get_arg_type (&arrayiter) != DBUS_TYPE_DICT_ENTRY) {
                  nih_free (*properties);
                  *properties = NULL;
                  dbus_message_unref (reply);
                  nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                                    _(NIH_DBUS_INVALID_ARGS_STR));
            }

            dbus_message_iter_recurse (&arrayiter, &dictiter);

            if (dbus_message_iter_get_arg_type (&dictiter) != DBUS_TYPE_STRING) {
                  nih_free (*properties);
                  *properties = NULL;
                  dbus_message_unref (reply);
                  nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                                    _(NIH_DBUS_INVALID_ARGS_STR));
            }

            dbus_message_iter_get_basic (&dictiter, &property);

            dbus_message_iter_next (&dictiter);

            if (dbus_message_iter_get_arg_type (&dictiter) != DBUS_TYPE_VARIANT) {
                  nih_free (*properties);
                  *properties = NULL;
                  dbus_message_unref (reply);
                  nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                                    _(NIH_DBUS_INVALID_ARGS_STR));
            }

            dbus_message_iter_recurse (&dictiter, &variter);

            if (! strcmp (property, "preferences")) {
                  /* Demarshal a structure from the message */
                  if (dbus_message_iter_get_arg_type (&variter) != DBUS_TYPE_STRUCT) {
                        nih_free (*properties);
                        *properties = NULL;
                        dbus_message_unref (reply);
                        nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                                          _(NIH_DBUS_INVALID_ARGS_STR));
                  }

                  dbus_message_iter_recurse (&variter, &preferences_iter);

                  preferences = nih_new (*properties, MyFooPreferences);
                  if (! preferences) {
                        goto enomem;
                  }

                  /* Demarshal a uint32_t from the message */
                  if (dbus_message_iter_get_arg_type (&preferences_iter) != DBUS_TYPE_UINT32) {
                        nih_free (preferences);
                        nih_free (*properties);
                        *properties = NULL;
                        dbus_message_unref (reply);
                        nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                                          _(NIH_DBUS_INVALID_ARGS_STR));
                  }

                  dbus_message_iter_get_basic (&preferences_iter, &preferences_item0);

                  dbus_message_iter_next (&preferences_iter);

                  preferences->item0 = preferences_item0;

                  /* Demarshal a char * from the message */
                  if (dbus_message_iter_get_arg_type (&preferences_iter) != DBUS_TYPE_STRING) {
                        nih_free (preferences);
                        nih_free (*properties);
                        *properties = NULL;
                        dbus_message_unref (reply);
                        nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                                          _(NIH_DBUS_INVALID_ARGS_STR));
                  }

                  dbus_message_iter_get_basic (&preferences_iter, &preferences_item1_dbus);

                  preferences_item1 = nih_strdup (preferences, preferences_item1_dbus);
                  if (! preferences_item1) {
                        nih_free (preferences);
                        goto enomem;
                  }

                  dbus_message_iter_next (&preferences_iter);

                  preferences->item1 = preferences_item1;

                  if (dbus_message_iter_get_arg_type (&preferences_iter) != DBUS_TYPE_INVALID) {
                        nih_free (preferences);
                        nih_free (*properties);
                        *properties = NULL;
                        dbus_message_unref (reply);
                        nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                                          _(NIH_DBUS_INVALID_ARGS_STR));
                  }

                  dbus_message_iter_next (&variter);

                  (*properties)->preferences = preferences;

                  nih_assert (++property_count);
            }

            dbus_message_iter_next (&dictiter);

            if (dbus_message_iter_get_arg_type (&dictiter) != DBUS_TYPE_INVALID) {
                  nih_free (*properties);
                  *properties = NULL;
                  dbus_message_unref (reply);
                  nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                                    _(NIH_DBUS_INVALID_ARGS_STR));
            }

            dbus_message_iter_next (&arrayiter);
      enomem: __attribute__ ((unused));
      }

      dbus_message_iter_next (&iter);

      if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) {
            nih_free (*properties);
            *properties = NULL;
            dbus_message_unref (reply);
            nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                              _(NIH_DBUS_INVALID_ARGS_STR));
      }

      if (property_count < 1) {
            nih_free (*properties);
            *properties = NULL;
            dbus_message_unref (reply);
            nih_return_error (-1, NIH_DBUS_INVALID_ARGS,
                              _(NIH_DBUS_INVALID_ARGS_STR));
      }

      dbus_message_unref (reply);

      return 0;
}

Generated by  Doxygen 1.6.0   Back to index