#include <gio/gio.h>
#include <glib-unix.h>
#include <stdlib.h>

static GDBusNodeInfo *introspection_data = NULL;
static guint registration_id = 0;
static GDBusConnection *g_connection = NULL;

static const gchar introspection_xml[] =
  "<node>"
  "  <interface name='org.myorg.MyObject'>"
  "    <property type='i' name='MyProperty' access='read'/>"
  "  </interface>"
  "</node>";

static void
handle_method_call (GDBusConnection       *connection,
                    const gchar           *sender,
                    const gchar           *object_path,
                    const gchar           *interface_name,
                    const gchar           *method_name,
                    GVariant              *parameters,
                    GDBusMethodInvocation *invocation,
                    gpointer               user_data)
{
  g_dbus_method_invocation_return_error_literal (invocation,
                                                 G_DBUS_ERROR,
                                                 G_DBUS_ERROR_NOT_SUPPORTED,
                                                 "");
}


static const GDBusInterfaceVTable interface_vtable =
{
  handle_method_call,
  NULL,
  NULL
};

static void
on_bus_acquired (GDBusConnection *connection,
                 const gchar     *name,
                 gpointer         user_data)
{
  g_connection = connection;

  registration_id = g_dbus_connection_register_object (connection,
                                                       "/org/myorg/MyObject",
                                                       introspection_data->interfaces[0],
                                                       &interface_vtable,
                                                       NULL,
                                                       NULL,  /* user_data_free_func */
                                                       NULL); /* GError** */
  g_assert (registration_id > 0);
}

static gboolean
on_sigint (gpointer user_data)
{
    GMainLoop *loop = (GMainLoop *) user_data;
    g_main_loop_quit(loop);
    return G_SOURCE_REMOVE;
}

int
main (int argc, char *argv[])
{
  guint owner_id;
  GMainLoop *loop;

  introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
  g_assert (introspection_data != NULL);

  owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
                             "org.myorg.MyObject",
                             G_BUS_NAME_OWNER_FLAGS_NONE,
                             on_bus_acquired,
                             NULL,
                             NULL,
                             NULL,
                             NULL);


  loop = g_main_loop_new (NULL, FALSE);
  g_unix_signal_add (SIGINT, on_sigint, loop);

  g_main_loop_run (loop);

  /* 
   * Need to explicitly free everything so that the memory leak
   * becomes apparent, instead of being lost in "still reachable" memory.
   */
  g_main_loop_unref(loop);
  g_bus_unown_name (owner_id);
  g_dbus_connection_unregister_object (g_connection, registration_id);
  g_dbus_node_info_unref (introspection_data);
  g_dbus_connection_close_sync (g_connection, NULL, NULL);

  return 0;
}
