Blame gio/gdbusdaemon.c

Packit ae235b
#include "config.h"
Packit ae235b
Packit ae235b
#include <string.h>
Packit ae235b
#include <stdlib.h>
Packit ae235b
Packit ae235b
#include <gstdio.h>
Packit ae235b
#include <gio/gio.h>
Packit ae235b
#include <gio/gunixsocketaddress.h>
Packit ae235b
#include "gdbusdaemon.h"
Packit ae235b
#include "glibintl.h"
Packit ae235b
Packit ae235b
#include "gdbus-daemon-generated.h"
Packit ae235b
Packit ae235b
#define DBUS_SERVICE_NAME  "org.freedesktop.DBus"
Packit ae235b
Packit ae235b
/* Owner flags */
Packit ae235b
#define DBUS_NAME_FLAG_ALLOW_REPLACEMENT 0x1 /**< Allow another service to become the primary owner if requested */
Packit ae235b
#define DBUS_NAME_FLAG_REPLACE_EXISTING  0x2 /**< Request to replace the current primary owner */
Packit ae235b
#define DBUS_NAME_FLAG_DO_NOT_QUEUE      0x4 /**< If we can not become the primary owner do not place us in the queue */
Packit ae235b
Packit ae235b
/* Replies to request for a name */
Packit ae235b
#define DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER  1 /**< Service has become the primary owner of the requested name */
Packit ae235b
#define DBUS_REQUEST_NAME_REPLY_IN_QUEUE       2 /**< Service could not become the primary owner and has been placed in the queue */
Packit ae235b
#define DBUS_REQUEST_NAME_REPLY_EXISTS         3 /**< Service is already in the queue */
Packit ae235b
#define DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER  4 /**< Service is already the primary owner */
Packit ae235b
Packit ae235b
/* Replies to releasing a name */
Packit ae235b
#define DBUS_RELEASE_NAME_REPLY_RELEASED        1 /**< Service was released from the given name */
Packit ae235b
#define DBUS_RELEASE_NAME_REPLY_NON_EXISTENT    2 /**< The given name does not exist on the bus */
Packit ae235b
#define DBUS_RELEASE_NAME_REPLY_NOT_OWNER       3 /**< Service is not an owner of the given name */
Packit ae235b
Packit ae235b
/* Replies to service starts */
Packit ae235b
#define DBUS_START_REPLY_SUCCESS         1 /**< Service was auto started */
Packit ae235b
#define DBUS_START_REPLY_ALREADY_RUNNING 2 /**< Service was already running */
Packit ae235b
Packit ae235b
#define IDLE_TIMEOUT_MSEC 3000
Packit ae235b
Packit ae235b
struct _GDBusDaemon
Packit ae235b
{
Packit ae235b
  _GFreedesktopDBusSkeleton parent_instance;
Packit ae235b
Packit ae235b
  gchar *address;
Packit ae235b
  guint timeout;
Packit ae235b
  gchar *tmpdir;
Packit ae235b
  GDBusServer *server;
Packit ae235b
  gchar *guid;
Packit ae235b
  GHashTable *clients;
Packit ae235b
  GHashTable *names;
Packit ae235b
  guint32 next_major_id;
Packit ae235b
  guint32 next_minor_id;
Packit ae235b
};
Packit ae235b
Packit ae235b
struct _GDBusDaemonClass
Packit ae235b
{
Packit ae235b
  _GFreedesktopDBusSkeletonClass parent_class;
Packit ae235b
};
Packit ae235b
Packit ae235b
enum {
Packit ae235b
  PROP_0,
Packit ae235b
  PROP_ADDRESS,
Packit ae235b
};
Packit ae235b
Packit ae235b
enum
Packit ae235b
{
Packit ae235b
  SIGNAL_IDLE_TIMEOUT,
Packit ae235b
  NR_SIGNALS
Packit ae235b
};
Packit ae235b
Packit ae235b
static guint g_dbus_daemon_signals[NR_SIGNALS];
Packit ae235b
Packit ae235b
Packit ae235b
static void initable_iface_init      (GInitableIface         *initable_iface);
Packit ae235b
static void g_dbus_daemon_iface_init (_GFreedesktopDBusIface *iface);
Packit ae235b
Packit ae235b
#define g_dbus_daemon_get_type _g_dbus_daemon_get_type
Packit ae235b
G_DEFINE_TYPE_WITH_CODE (GDBusDaemon, g_dbus_daemon, _G_TYPE_FREEDESKTOP_DBUS_SKELETON,
Packit ae235b
			 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)
Packit ae235b
			 G_IMPLEMENT_INTERFACE (_G_TYPE_FREEDESKTOP_DBUS, g_dbus_daemon_iface_init))
Packit ae235b
Packit ae235b
typedef struct {
Packit ae235b
  GDBusDaemon *daemon;
Packit ae235b
  char *id;
Packit ae235b
  GDBusConnection *connection;
Packit ae235b
  GList *matches;
Packit ae235b
} Client;
Packit ae235b
Packit ae235b
typedef struct {
Packit ae235b
  Client *client;
Packit ae235b
  guint32 flags;
Packit ae235b
} NameOwner;
Packit ae235b
Packit ae235b
typedef struct {
Packit ae235b
  int refcount;
Packit ae235b
Packit ae235b
  char *name;
Packit ae235b
  GDBusDaemon *daemon;
Packit ae235b
Packit ae235b
  NameOwner *owner;
Packit ae235b
  GList *queue;
Packit ae235b
} Name;
Packit ae235b
Packit ae235b
enum {
Packit ae235b
  MATCH_ELEMENT_TYPE,
Packit ae235b
  MATCH_ELEMENT_SENDER,
Packit ae235b
  MATCH_ELEMENT_INTERFACE,
Packit ae235b
  MATCH_ELEMENT_MEMBER,
Packit ae235b
  MATCH_ELEMENT_PATH,
Packit ae235b
  MATCH_ELEMENT_PATH_NAMESPACE,
Packit ae235b
  MATCH_ELEMENT_DESTINATION,
Packit ae235b
  MATCH_ELEMENT_ARG0NAMESPACE,
Packit ae235b
  MATCH_ELEMENT_EAVESDROP,
Packit ae235b
  MATCH_ELEMENT_ARGN,
Packit ae235b
  MATCH_ELEMENT_ARGNPATH,
Packit ae235b
};
Packit ae235b
Packit ae235b
typedef struct {
Packit ae235b
  guint16 type;
Packit ae235b
  guint16 arg;
Packit ae235b
  char *value;
Packit ae235b
} MatchElement;
Packit ae235b
Packit ae235b
typedef struct {
Packit ae235b
  gboolean eavesdrop;
Packit ae235b
  GDBusMessageType type;
Packit ae235b
  int n_elements;
Packit ae235b
  MatchElement *elements;
Packit ae235b
} Match;
Packit ae235b
Packit ae235b
static GDBusMessage *filter_function   (GDBusConnection *connection,
Packit ae235b
					GDBusMessage    *message,
Packit ae235b
					gboolean         incoming,
Packit ae235b
					gpointer         user_data);
Packit ae235b
static void          connection_closed (GDBusConnection *connection,
Packit ae235b
					gboolean         remote_peer_vanished,
Packit ae235b
					GError          *error,
Packit ae235b
					Client          *client);
Packit ae235b
Packit ae235b
static NameOwner *
Packit ae235b
name_owner_new (Client *client, guint32 flags)
Packit ae235b
{
Packit ae235b
  NameOwner *owner;
Packit ae235b
Packit ae235b
  owner = g_new0 (NameOwner, 1);
Packit ae235b
  owner->client = client;
Packit ae235b
  owner->flags = flags;
Packit ae235b
  return owner;
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
name_owner_free (NameOwner *owner)
Packit ae235b
{
Packit ae235b
  g_free (owner);
Packit ae235b
}
Packit ae235b
Packit ae235b
static Name *
Packit ae235b
name_new (GDBusDaemon *daemon, const char *str)
Packit ae235b
{
Packit ae235b
  Name *name;
Packit ae235b
Packit ae235b
  name = g_new0 (Name, 1);
Packit ae235b
  name->refcount = 1;
Packit ae235b
  name->daemon = daemon;
Packit ae235b
  name->name = g_strdup (str);
Packit ae235b
Packit ae235b
  g_hash_table_insert (daemon->names, name->name, name);
Packit ae235b
Packit ae235b
  return name;
Packit ae235b
}
Packit ae235b
Packit ae235b
static Name *
Packit ae235b
name_ref (Name *name)
Packit ae235b
{
Packit ae235b
  name->refcount++;
Packit ae235b
  return name;
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
name_unref (Name *name)
Packit ae235b
{
Packit ae235b
  if (--name->refcount == 0)
Packit ae235b
    {
Packit ae235b
      g_hash_table_remove (name->daemon->names, name->name);
Packit ae235b
      g_free (name->name);
Packit ae235b
      g_free (name);
Packit ae235b
    }
Packit ae235b
}
Packit ae235b
Packit ae235b
static Name *
Packit ae235b
name_ensure (GDBusDaemon *daemon, const char *str)
Packit ae235b
{
Packit ae235b
  Name *name;
Packit ae235b
Packit ae235b
  name = g_hash_table_lookup (daemon->names, str);
Packit ae235b
Packit ae235b
  if (name != NULL)
Packit ae235b
    return name_ref (name);
Packit ae235b
  return name_new (daemon, str);
Packit ae235b
}
Packit ae235b
Packit ae235b
static Name *
Packit ae235b
name_lookup (GDBusDaemon *daemon, const char *str)
Packit ae235b
{
Packit ae235b
  return g_hash_table_lookup (daemon->names, str);
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
is_key (const char *key_start, const char *key_end, char *value)
Packit ae235b
{
Packit ae235b
  gsize len = strlen (value);
Packit ae235b
Packit ae235b
  if (len != key_end - key_start)
Packit ae235b
    return FALSE;
Packit ae235b
Packit ae235b
  return strncmp (key_start, value, len) == 0;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
parse_key (MatchElement *element, const char *key_start, const char *key_end)
Packit ae235b
{
Packit ae235b
  gboolean res = TRUE;
Packit ae235b
Packit ae235b
  if (is_key (key_start, key_end, "type"))
Packit ae235b
    {
Packit ae235b
      element->type = MATCH_ELEMENT_TYPE;
Packit ae235b
    }
Packit ae235b
  else if (is_key (key_start, key_end, "sender"))
Packit ae235b
    {
Packit ae235b
      element->type = MATCH_ELEMENT_SENDER;
Packit ae235b
    }
Packit ae235b
  else if (is_key (key_start, key_end, "interface"))
Packit ae235b
    {
Packit ae235b
      element->type = MATCH_ELEMENT_INTERFACE;
Packit ae235b
    }
Packit ae235b
  else if (is_key (key_start, key_end, "member"))
Packit ae235b
    {
Packit ae235b
      element->type = MATCH_ELEMENT_MEMBER;
Packit ae235b
    }
Packit ae235b
  else if (is_key (key_start, key_end, "path"))
Packit ae235b
    {
Packit ae235b
      element->type = MATCH_ELEMENT_PATH;
Packit ae235b
    }
Packit ae235b
  else if (is_key (key_start, key_end, "path_namespace"))
Packit ae235b
    {
Packit ae235b
      element->type = MATCH_ELEMENT_PATH_NAMESPACE;
Packit ae235b
    }
Packit ae235b
  else if (is_key (key_start, key_end, "destination"))
Packit ae235b
    {
Packit ae235b
      element->type = MATCH_ELEMENT_DESTINATION;
Packit ae235b
    }
Packit ae235b
  else if (is_key (key_start, key_end, "arg0namespace"))
Packit ae235b
    {
Packit ae235b
      element->type = MATCH_ELEMENT_ARG0NAMESPACE;
Packit ae235b
    }
Packit ae235b
  else if (is_key (key_start, key_end, "eavesdrop"))
Packit ae235b
    {
Packit ae235b
      element->type = MATCH_ELEMENT_EAVESDROP;
Packit ae235b
    }
Packit ae235b
  else if (key_end - key_start > 3 && is_key (key_start, key_start + 3, "arg"))
Packit ae235b
    {
Packit ae235b
      const char *digits = key_start + 3;
Packit ae235b
      const char *end_digits = digits;
Packit ae235b
Packit ae235b
      while (end_digits < key_end && g_ascii_isdigit (*end_digits))
Packit ae235b
	end_digits++;
Packit ae235b
Packit ae235b
      if (end_digits == key_end) /* argN */
Packit ae235b
	{
Packit ae235b
	  element->type = MATCH_ELEMENT_ARGN;
Packit ae235b
	  element->arg = atoi (digits);
Packit ae235b
	}
Packit ae235b
      else if (is_key (end_digits, key_end, "path")) /* argNpath */
Packit ae235b
	{
Packit ae235b
	  element->type = MATCH_ELEMENT_ARGNPATH;
Packit ae235b
	  element->arg = atoi (digits);
Packit ae235b
	}
Packit ae235b
      else
Packit ae235b
	res = FALSE;
Packit ae235b
    }
Packit ae235b
  else
Packit ae235b
    res = FALSE;
Packit ae235b
Packit ae235b
  return res;
Packit ae235b
}
Packit ae235b
Packit ae235b
static const char *
Packit ae235b
parse_value (MatchElement *element, const char *s)
Packit ae235b
{
Packit ae235b
  char quote_char;
Packit ae235b
  GString *value;
Packit ae235b
Packit ae235b
  value = g_string_new ("");
Packit ae235b
Packit ae235b
  quote_char = 0;
Packit ae235b
Packit ae235b
  for (;*s; s++)
Packit ae235b
    {
Packit ae235b
      if (quote_char == 0)
Packit ae235b
	{
Packit ae235b
	  switch (*s)
Packit ae235b
	    {
Packit ae235b
	    case '\'':
Packit ae235b
	      quote_char = '\'';
Packit ae235b
	      break;
Packit ae235b
Packit ae235b
	    case ',':
Packit ae235b
	      s++;
Packit ae235b
	      goto out;
Packit ae235b
Packit ae235b
	    case '\\':
Packit ae235b
	      quote_char = '\\';
Packit ae235b
	      break;
Packit ae235b
Packit ae235b
	    default:
Packit ae235b
	      g_string_append_c (value, *s);
Packit ae235b
	      break;
Packit ae235b
	    }
Packit ae235b
	}
Packit ae235b
      else if (quote_char == '\\')
Packit ae235b
	{
Packit ae235b
	  /* \ only counts as an escape if escaping a quote mark */
Packit ae235b
	  if (*s != '\'')
Packit ae235b
	    g_string_append_c (value, '\\');
Packit ae235b
Packit ae235b
	  g_string_append_c (value, *s);
Packit ae235b
	  quote_char = 0;
Packit ae235b
	}
Packit ae235b
      else /* quote_char == ' */
Packit ae235b
	{
Packit ae235b
	  if (*s == '\'')
Packit ae235b
	    quote_char = 0;
Packit ae235b
	  else
Packit ae235b
	    g_string_append_c (value, *s);
Packit ae235b
	}
Packit ae235b
    }
Packit ae235b
Packit ae235b
 out:
Packit ae235b
Packit ae235b
  if (quote_char == '\\')
Packit ae235b
    g_string_append_c (value, '\\');
Packit ae235b
  else if (quote_char == '\'')
Packit ae235b
    {
Packit ae235b
      g_string_free (value, TRUE);
Packit ae235b
      return NULL;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  element->value = g_string_free (value, FALSE);
Packit ae235b
  return s;
Packit ae235b
}
Packit ae235b
Packit ae235b
static Match *
Packit ae235b
match_new (const char *str)
Packit ae235b
{
Packit ae235b
  Match *match;
Packit ae235b
  GArray *elements;
Packit ae235b
  const char *p;
Packit ae235b
  const char *key_start;
Packit ae235b
  const char *key_end;
Packit ae235b
  MatchElement element;
Packit ae235b
  gboolean eavesdrop;
Packit ae235b
  GDBusMessageType type;
Packit ae235b
  int i;
Packit ae235b
Packit ae235b
  eavesdrop = FALSE;
Packit ae235b
  type = G_DBUS_MESSAGE_TYPE_INVALID;
Packit ae235b
  elements = g_array_new (TRUE, TRUE, sizeof (MatchElement));
Packit ae235b
Packit ae235b
  p = str;
Packit ae235b
Packit ae235b
  while (*p != 0)
Packit ae235b
    {
Packit ae235b
      memset (&element, 0, sizeof (element));
Packit ae235b
Packit ae235b
      /* Skip initial whitespace */
Packit ae235b
      while (*p && g_ascii_isspace (*p))
Packit ae235b
	p++;
Packit ae235b
Packit ae235b
      key_start = p;
Packit ae235b
Packit ae235b
      /* Read non-whitespace non-equals chars */
Packit ae235b
      while (*p && *p != '=' && !g_ascii_isspace (*p))
Packit ae235b
	p++;
Packit ae235b
Packit ae235b
      key_end = p;
Packit ae235b
Packit ae235b
      /* Skip any whitespace after key */
Packit ae235b
      while (*p && g_ascii_isspace (*p))
Packit ae235b
	p++;
Packit ae235b
Packit ae235b
      if (key_start == key_end)
Packit ae235b
	continue; /* Allow trailing whitespace */
Packit ae235b
Packit ae235b
      if (*p != '=')
Packit ae235b
	goto error;
Packit ae235b
Packit ae235b
      ++p;
Packit ae235b
Packit ae235b
      if (!parse_key (&element, key_start, key_end))
Packit ae235b
	goto error;
Packit ae235b
Packit ae235b
      p = parse_value (&element, p);
Packit ae235b
      if (p == NULL)
Packit ae235b
	goto error;
Packit ae235b
Packit ae235b
      if (element.type == MATCH_ELEMENT_EAVESDROP)
Packit ae235b
	{
Packit ae235b
	  if (strcmp (element.value, "true") == 0)
Packit ae235b
	    eavesdrop = TRUE;
Packit ae235b
	  else if (strcmp (element.value, "false") == 0)
Packit ae235b
	    eavesdrop = FALSE;
Packit ae235b
	  else
Packit ae235b
	    {
Packit ae235b
	      g_free (element.value);
Packit ae235b
	      goto error;
Packit ae235b
	    }
Packit ae235b
	  g_free (element.value);
Packit ae235b
	}
Packit ae235b
      else if (element.type == MATCH_ELEMENT_TYPE)
Packit ae235b
	{
Packit ae235b
	  if (strcmp (element.value, "signal") == 0)
Packit ae235b
	    type = G_DBUS_MESSAGE_TYPE_SIGNAL;
Packit ae235b
	  else if (strcmp (element.value, "method_call") == 0)
Packit ae235b
	    type = G_DBUS_MESSAGE_TYPE_METHOD_CALL;
Packit ae235b
	  else if (strcmp (element.value, "method_return") == 0)
Packit ae235b
	    type = G_DBUS_MESSAGE_TYPE_METHOD_RETURN;
Packit ae235b
	  else if (strcmp (element.value, "error") == 0)
Packit ae235b
	    type = G_DBUS_MESSAGE_TYPE_ERROR;
Packit ae235b
	  else
Packit ae235b
	    {
Packit ae235b
	      g_free (element.value);
Packit ae235b
	      goto error;
Packit ae235b
	    }
Packit ae235b
	  g_free (element.value);
Packit ae235b
	}
Packit ae235b
      else
Packit ae235b
	g_array_append_val (elements, element);
Packit ae235b
    }
Packit ae235b
Packit ae235b
  match = g_new0 (Match, 1);
Packit ae235b
  match->n_elements = elements->len;
Packit ae235b
  match->elements = (MatchElement *)g_array_free (elements, FALSE);
Packit ae235b
  match->eavesdrop = eavesdrop;
Packit ae235b
  match->type = type;
Packit ae235b
Packit ae235b
  return match;
Packit ae235b
Packit ae235b
 error:
Packit ae235b
  for (i = 0; i < elements->len; i++)
Packit ae235b
    g_free (g_array_index (elements, MatchElement, i).value);
Packit ae235b
  g_array_free (elements, TRUE);
Packit ae235b
  return NULL;
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
match_free (Match *match)
Packit ae235b
{
Packit ae235b
  int i;
Packit ae235b
  for (i = 0; i < match->n_elements; i++)
Packit ae235b
    g_free (match->elements[i].value);
Packit ae235b
  g_free (match->elements);
Packit ae235b
  g_free (match);
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
match_equal (Match *a, Match *b)
Packit ae235b
{
Packit ae235b
  int i;
Packit ae235b
Packit ae235b
  if (a->eavesdrop != b->eavesdrop)
Packit ae235b
    return FALSE;
Packit ae235b
  if (a->type != b->type)
Packit ae235b
    return FALSE;
Packit ae235b
 if (a->n_elements != b->n_elements)
Packit ae235b
    return FALSE;
Packit ae235b
  for (i = 0; i < a->n_elements; i++)
Packit ae235b
    {
Packit ae235b
      if (a->elements[i].type != b->elements[i].type ||
Packit ae235b
	  a->elements[i].arg != b->elements[i].arg ||
Packit ae235b
	  strcmp (a->elements[i].value, b->elements[i].value) != 0)
Packit ae235b
	return FALSE;
Packit ae235b
    }
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static const gchar *
Packit ae235b
message_get_argN (GDBusMessage *message, int n, gboolean allow_path)
Packit ae235b
{
Packit ae235b
  const gchar *ret;
Packit ae235b
  GVariant *body;
Packit ae235b
Packit ae235b
  ret = NULL;
Packit ae235b
Packit ae235b
  body = g_dbus_message_get_body (message);
Packit ae235b
Packit ae235b
  if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE_TUPLE))
Packit ae235b
    {
Packit ae235b
      GVariant *item;
Packit ae235b
      item = g_variant_get_child_value (body, n);
Packit ae235b
      if (g_variant_is_of_type (item, G_VARIANT_TYPE_STRING) ||
Packit ae235b
	  (allow_path && g_variant_is_of_type (item, G_VARIANT_TYPE_OBJECT_PATH)))
Packit ae235b
	ret = g_variant_get_string (item, NULL);
Packit ae235b
      g_variant_unref (item);
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return ret;
Packit ae235b
}
Packit ae235b
Packit ae235b
enum {
Packit ae235b
  CHECK_TYPE_STRING,
Packit ae235b
  CHECK_TYPE_NAME,
Packit ae235b
  CHECK_TYPE_PATH_PREFIX,
Packit ae235b
  CHECK_TYPE_PATH_RELATED,
Packit ae235b
  CHECK_TYPE_NAMESPACE_PREFIX
Packit ae235b
};
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
match_matches (GDBusDaemon *daemon,
Packit ae235b
	       Match *match, GDBusMessage *message,
Packit ae235b
	       gboolean has_destination)
Packit ae235b
{
Packit ae235b
  MatchElement *element;
Packit ae235b
  Name *name;
Packit ae235b
  int i, len, len2;
Packit ae235b
  const char *value;
Packit ae235b
  int check_type;
Packit ae235b
Packit ae235b
  if (has_destination && !match->eavesdrop)
Packit ae235b
    return FALSE;
Packit ae235b
Packit ae235b
  if (match->type != G_DBUS_MESSAGE_TYPE_INVALID &&
Packit ae235b
      g_dbus_message_get_message_type (message) != match->type)
Packit ae235b
    return FALSE;
Packit ae235b
Packit ae235b
  for (i = 0; i < match->n_elements; i++)
Packit ae235b
    {
Packit ae235b
      element = &match->elements[i];
Packit ae235b
      check_type = CHECK_TYPE_STRING;
Packit ae235b
      switch (element->type)
Packit ae235b
	{
Packit ae235b
	case MATCH_ELEMENT_SENDER:
Packit ae235b
	  check_type = CHECK_TYPE_NAME;
Packit ae235b
	  value = g_dbus_message_get_sender (message);
Packit ae235b
	  if (value == NULL)
Packit ae235b
	    value = DBUS_SERVICE_NAME;
Packit ae235b
	  break;
Packit ae235b
	case MATCH_ELEMENT_DESTINATION:
Packit ae235b
	  check_type = CHECK_TYPE_NAME;
Packit ae235b
	  value = g_dbus_message_get_destination (message);
Packit ae235b
	  break;
Packit ae235b
	case MATCH_ELEMENT_INTERFACE:
Packit ae235b
	  value = g_dbus_message_get_interface (message);
Packit ae235b
	  break;
Packit ae235b
	case MATCH_ELEMENT_MEMBER:
Packit ae235b
	  value = g_dbus_message_get_member (message);
Packit ae235b
	  break;
Packit ae235b
	case MATCH_ELEMENT_PATH:
Packit ae235b
	  value = g_dbus_message_get_path (message);
Packit ae235b
	  break;
Packit ae235b
	case MATCH_ELEMENT_PATH_NAMESPACE:
Packit ae235b
	  check_type = CHECK_TYPE_PATH_PREFIX;
Packit ae235b
	  value = g_dbus_message_get_path (message);
Packit ae235b
	  break;
Packit ae235b
	case MATCH_ELEMENT_ARG0NAMESPACE:
Packit ae235b
	  check_type = CHECK_TYPE_NAMESPACE_PREFIX;
Packit ae235b
	  value = message_get_argN (message, 0, FALSE);
Packit ae235b
	  break;
Packit ae235b
	case MATCH_ELEMENT_ARGN:
Packit ae235b
	  value = message_get_argN (message, element->arg, FALSE);
Packit ae235b
	  break;
Packit ae235b
	case MATCH_ELEMENT_ARGNPATH:
Packit ae235b
	  check_type = CHECK_TYPE_PATH_RELATED;
Packit ae235b
	  value = message_get_argN (message, element->arg, TRUE);
Packit ae235b
	  break;
Packit ae235b
	default:
Packit ae235b
	case MATCH_ELEMENT_TYPE:
Packit ae235b
	case MATCH_ELEMENT_EAVESDROP:
Packit ae235b
	  g_assert_not_reached ();
Packit ae235b
	}
Packit ae235b
Packit ae235b
      if (value == NULL)
Packit ae235b
	return FALSE;
Packit ae235b
Packit ae235b
      switch (check_type)
Packit ae235b
	{
Packit ae235b
	case CHECK_TYPE_STRING:
Packit ae235b
	  if (strcmp (element->value, value) != 0)
Packit ae235b
	    return FALSE;
Packit ae235b
	  break;
Packit ae235b
	case CHECK_TYPE_NAME:
Packit ae235b
	  name = name_lookup (daemon, element->value);
Packit ae235b
	  if (name != NULL && name->owner != NULL)
Packit ae235b
	    {
Packit ae235b
	      if (strcmp (name->owner->client->id, value) != 0)
Packit ae235b
		return FALSE;
Packit ae235b
	    }
Packit ae235b
	  else if (strcmp (element->value, value) != 0)
Packit ae235b
	    return FALSE;
Packit ae235b
	  break;
Packit ae235b
	case CHECK_TYPE_PATH_PREFIX:
Packit ae235b
	  len = strlen (element->value);
Packit ae235b
Packit ae235b
	  /* Make sure to handle the case of element->value == '/'. */
Packit ae235b
	  if (len == 1)
Packit ae235b
	    break;
Packit ae235b
Packit ae235b
	  /* Fail if there's no prefix match, or if the prefix match doesn't
Packit ae235b
	   * finish at the end of or at a separator in the @value. */
Packit ae235b
	  if (!g_str_has_prefix (value, element->value))
Packit ae235b
	    return FALSE;
Packit ae235b
	  if (value[len] != 0 && value[len] != '/')
Packit ae235b
	    return FALSE;
Packit ae235b
Packit ae235b
	  break;
Packit ae235b
	case CHECK_TYPE_PATH_RELATED:
Packit ae235b
	  len = strlen (element->value);
Packit ae235b
	  len2 = strlen (value);
Packit ae235b
Packit ae235b
	  if (!(strcmp (value, element->value) == 0 ||
Packit ae235b
		(len2 > 0 && value[len2-1] == '/' && g_str_has_prefix (element->value, value)) ||
Packit ae235b
		(len > 0 && element->value[len-1] == '/' && g_str_has_prefix (value, element->value))))
Packit ae235b
	    return FALSE;
Packit ae235b
	  break;
Packit ae235b
	case CHECK_TYPE_NAMESPACE_PREFIX:
Packit ae235b
	  len = strlen (element->value);
Packit ae235b
	  if (!(g_str_has_prefix (value, element->value) &&
Packit ae235b
		(value[len] == 0 || value[len] == '.')))
Packit ae235b
	    return FALSE;
Packit ae235b
	  break;
Packit ae235b
	default:
Packit ae235b
	  g_assert_not_reached ();
Packit ae235b
	}
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
broadcast_message (GDBusDaemon *daemon,
Packit ae235b
		   GDBusMessage *message,
Packit ae235b
		   gboolean has_destination,
Packit ae235b
		   gboolean preserve_serial,
Packit ae235b
		   Client *not_to)
Packit ae235b
{
Packit ae235b
  GList *clients, *l, *ll;
Packit ae235b
  GDBusMessage *copy;
Packit ae235b
Packit ae235b
  clients = g_hash_table_get_values (daemon->clients);
Packit ae235b
  for (l = clients; l != NULL; l = l->next)
Packit ae235b
    {
Packit ae235b
      Client *client = l->data;
Packit ae235b
Packit ae235b
      if (client == not_to)
Packit ae235b
	continue;
Packit ae235b
Packit ae235b
      for (ll = client->matches; ll != NULL; ll = ll->next)
Packit ae235b
	{
Packit ae235b
	  Match *match = ll->data;
Packit ae235b
Packit ae235b
	  if (match_matches (daemon, match, message, has_destination))
Packit ae235b
	    break;
Packit ae235b
	}
Packit ae235b
Packit ae235b
      if (ll != NULL)
Packit ae235b
	{
Packit ae235b
	  copy = g_dbus_message_copy (message, NULL);
Packit ae235b
	  if (copy)
Packit ae235b
	    {
Packit ae235b
	      g_dbus_connection_send_message (client->connection, copy,
Packit ae235b
					      preserve_serial?G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL:0, NULL, NULL);
Packit ae235b
	      g_object_unref (copy);
Packit ae235b
	    }
Packit ae235b
	}
Packit ae235b
    }
Packit ae235b
Packit ae235b
  g_list_free (clients);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
send_name_owner_changed (GDBusDaemon *daemon,
Packit ae235b
			 const char *name,
Packit ae235b
			 const char *old_owner,
Packit ae235b
			 const char *new_owner)
Packit ae235b
{
Packit ae235b
  GDBusMessage *signal_message;
Packit ae235b
Packit ae235b
  signal_message = g_dbus_message_new_signal ("/org/freedesktop/DBus",
Packit ae235b
					      "org.freedesktop.DBus",
Packit ae235b
					      "NameOwnerChanged");
Packit ae235b
  g_dbus_message_set_body (signal_message,
Packit ae235b
			   g_variant_new ("(sss)",
Packit ae235b
					  name,
Packit ae235b
					  old_owner ? old_owner : "",
Packit ae235b
					  new_owner ? new_owner : ""));
Packit ae235b
Packit ae235b
  broadcast_message (daemon, signal_message, FALSE, FALSE, NULL);
Packit ae235b
  g_object_unref (signal_message);
Packit ae235b
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
name_unqueue_owner (Name *name, Client *client)
Packit ae235b
{
Packit ae235b
  GList *l;
Packit ae235b
Packit ae235b
  for (l = name->queue; l != NULL; l = l->next)
Packit ae235b
    {
Packit ae235b
      NameOwner *other = l->data;
Packit ae235b
Packit ae235b
      if (other->client == client)
Packit ae235b
	{
Packit ae235b
	  name->queue = g_list_delete_link (name->queue, l);
Packit ae235b
	  name_unref (name);
Packit ae235b
	  name_owner_free (other);
Packit ae235b
	  return TRUE;
Packit ae235b
	}
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return FALSE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
name_replace_owner (Name *name, NameOwner *owner)
Packit ae235b
{
Packit ae235b
  GDBusDaemon *daemon = name->daemon;
Packit ae235b
  NameOwner *old_owner;
Packit ae235b
  char *old_name = NULL, *new_name = NULL;
Packit ae235b
  Client *new_client = NULL;
Packit ae235b
Packit ae235b
  if (owner)
Packit ae235b
    new_client = owner->client;
Packit ae235b
Packit ae235b
  name_ref (name);
Packit ae235b
Packit ae235b
  old_owner = name->owner;
Packit ae235b
  if (old_owner)
Packit ae235b
    {
Packit ae235b
      Client *old_client = old_owner->client;
Packit ae235b
Packit ae235b
      g_assert (old_owner->client != new_client);
Packit ae235b
Packit ae235b
      g_dbus_connection_emit_signal (old_client->connection,
Packit ae235b
				     NULL, "/org/freedesktop/DBus",
Packit ae235b
				     "org.freedesktop.DBus", "NameLost",
Packit ae235b
				     g_variant_new ("(s)",
Packit ae235b
						    name->name), NULL);
Packit ae235b
Packit ae235b
      old_name = g_strdup (old_client->id);
Packit ae235b
      if (old_owner->flags & DBUS_NAME_FLAG_DO_NOT_QUEUE)
Packit ae235b
	{
Packit ae235b
	  name_unref (name);
Packit ae235b
	  name_owner_free (old_owner);
Packit ae235b
	}
Packit ae235b
      else
Packit ae235b
	name->queue = g_list_prepend (name->queue, old_owner);
Packit ae235b
    }
Packit ae235b
Packit ae235b
  name->owner = owner;
Packit ae235b
  if (owner)
Packit ae235b
    {
Packit ae235b
      name_unqueue_owner (name, owner->client);
Packit ae235b
      name_ref (name);
Packit ae235b
      new_name = new_client->id;
Packit ae235b
Packit ae235b
      g_dbus_connection_emit_signal (new_client->connection,
Packit ae235b
				     NULL, "/org/freedesktop/DBus",
Packit ae235b
				     "org.freedesktop.DBus", "NameAcquired",
Packit ae235b
				     g_variant_new ("(s)",
Packit ae235b
						    name->name), NULL);
Packit ae235b
    }
Packit ae235b
Packit ae235b
  send_name_owner_changed (daemon, name->name, old_name, new_name);
Packit ae235b
Packit ae235b
  g_free (old_name);
Packit ae235b
Packit ae235b
  name_unref (name);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
name_release_owner (Name *name)
Packit ae235b
{
Packit ae235b
  NameOwner *next_owner = NULL;
Packit ae235b
Packit ae235b
  name_ref (name);
Packit ae235b
Packit ae235b
  /* Will someone else take over? */
Packit ae235b
  if (name->queue)
Packit ae235b
    {
Packit ae235b
      next_owner = name->queue->data;
Packit ae235b
      name_unref (name);
Packit ae235b
      name->queue = g_list_delete_link (name->queue, name->queue);
Packit ae235b
    }
Packit ae235b
Packit ae235b
  name->owner->flags |= DBUS_NAME_FLAG_DO_NOT_QUEUE;
Packit ae235b
  name_replace_owner (name, next_owner);
Packit ae235b
Packit ae235b
  name_unref (name);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
name_queue_owner (Name *name, NameOwner *owner)
Packit ae235b
{
Packit ae235b
  GList *l;
Packit ae235b
Packit ae235b
  for (l = name->queue; l != NULL; l = l->next)
Packit ae235b
    {
Packit ae235b
      NameOwner *other = l->data;
Packit ae235b
Packit ae235b
      if (other->client == owner->client)
Packit ae235b
	{
Packit ae235b
	  other->flags = owner->flags;
Packit ae235b
	  name_owner_free (owner);
Packit ae235b
	  return;
Packit ae235b
	}
Packit ae235b
    }
Packit ae235b
Packit ae235b
  name->queue = g_list_append (name->queue, owner);
Packit ae235b
  name_ref (name);
Packit ae235b
}
Packit ae235b
Packit ae235b
static Client *
Packit ae235b
client_new (GDBusDaemon *daemon, GDBusConnection *connection)
Packit ae235b
{
Packit ae235b
  Client *client;
Packit ae235b
  GError *error = NULL;
Packit ae235b
Packit ae235b
  client = g_new0 (Client, 1);
Packit ae235b
  client->daemon = daemon;
Packit ae235b
  client->id = g_strdup_printf (":%d.%d", daemon->next_major_id, daemon->next_minor_id);
Packit ae235b
  client->connection = g_object_ref (connection);
Packit ae235b
Packit ae235b
  if (daemon->next_minor_id == G_MAXUINT32)
Packit ae235b
    {
Packit ae235b
      daemon->next_minor_id = 0;
Packit ae235b
      daemon->next_major_id++;
Packit ae235b
    }
Packit ae235b
  else
Packit ae235b
    daemon->next_minor_id++;
Packit ae235b
Packit ae235b
  g_object_set_data (G_OBJECT (connection), "client", client);
Packit ae235b
  g_hash_table_insert (daemon->clients, client->id, client);
Packit ae235b
Packit ae235b
  g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (daemon), connection,
Packit ae235b
				    "/org/freedesktop/DBus", &error);
Packit ae235b
  g_assert_no_error (error);
Packit ae235b
Packit ae235b
  g_signal_connect (connection, "closed", G_CALLBACK (connection_closed), client);
Packit ae235b
  g_dbus_connection_add_filter (connection,
Packit ae235b
				filter_function,
Packit ae235b
				client, NULL);
Packit ae235b
Packit ae235b
  send_name_owner_changed (daemon, client->id, NULL, client->id);
Packit ae235b
Packit ae235b
  return client;
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
client_free (Client *client)
Packit ae235b
{
Packit ae235b
  GDBusDaemon *daemon = client->daemon;
Packit ae235b
  GList *l, *names;
Packit ae235b
Packit ae235b
  g_dbus_interface_skeleton_unexport_from_connection (G_DBUS_INTERFACE_SKELETON (daemon),
Packit ae235b
						      client->connection);
Packit ae235b
Packit ae235b
  g_hash_table_remove (daemon->clients, client->id);
Packit ae235b
Packit ae235b
  names = g_hash_table_get_values (daemon->names);
Packit ae235b
  for (l = names; l != NULL; l = l->next)
Packit ae235b
    {
Packit ae235b
      Name *name = l->data;
Packit ae235b
Packit ae235b
      name_ref (name);
Packit ae235b
Packit ae235b
      if (name->owner && name->owner->client == client)
Packit ae235b
	name_release_owner (name);
Packit ae235b
Packit ae235b
      name_unqueue_owner (name, client);
Packit ae235b
Packit ae235b
      name_unref (name);
Packit ae235b
    }
Packit ae235b
  g_list_free (names);
Packit ae235b
Packit ae235b
  send_name_owner_changed (daemon, client->id, client->id, NULL);
Packit ae235b
Packit ae235b
  g_object_unref (client->connection);
Packit ae235b
Packit ae235b
  for (l = client->matches; l != NULL; l = l->next)
Packit ae235b
    match_free (l->data);
Packit ae235b
  g_list_free (client->matches);
Packit ae235b
Packit ae235b
  g_free (client->id);
Packit ae235b
  g_free (client);
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
idle_timeout_cb (gpointer user_data)
Packit ae235b
{
Packit ae235b
  GDBusDaemon *daemon = user_data;
Packit ae235b
Packit ae235b
  daemon->timeout = 0;
Packit ae235b
Packit ae235b
  g_signal_emit (daemon,
Packit ae235b
		 g_dbus_daemon_signals[SIGNAL_IDLE_TIMEOUT],
Packit ae235b
		 0);
Packit ae235b
Packit ae235b
  return G_SOURCE_REMOVE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
connection_closed (GDBusConnection *connection,
Packit ae235b
		   gboolean remote_peer_vanished,
Packit ae235b
		   GError *error,
Packit ae235b
		   Client *client)
Packit ae235b
{
Packit ae235b
  GDBusDaemon *daemon = client->daemon;
Packit ae235b
Packit ae235b
  client_free (client);
Packit ae235b
Packit ae235b
  if (g_hash_table_size (daemon->clients) == 0)
Packit ae235b
    daemon->timeout = g_timeout_add (IDLE_TIMEOUT_MSEC,
Packit ae235b
				     idle_timeout_cb,
Packit ae235b
				     daemon);
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
handle_add_match (_GFreedesktopDBus *object,
Packit ae235b
		  GDBusMethodInvocation *invocation,
Packit ae235b
		  const gchar *arg_rule)
Packit ae235b
{
Packit ae235b
  Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
Packit ae235b
  Match *match;
Packit ae235b
Packit ae235b
  match = match_new (arg_rule);
Packit ae235b
Packit ae235b
  if (match == NULL)
Packit ae235b
    g_dbus_method_invocation_return_error (invocation,
Packit ae235b
					   G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_INVALID,
Packit ae235b
					   "Invalid rule: %s", arg_rule);
Packit ae235b
  else
Packit ae235b
    {
Packit ae235b
      client->matches = g_list_prepend (client->matches, match);
Packit ae235b
      _g_freedesktop_dbus_complete_add_match (object, invocation);
Packit ae235b
    }
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
handle_get_connection_selinux_security_context (_GFreedesktopDBus *object,
Packit ae235b
						GDBusMethodInvocation *invocation,
Packit ae235b
						const gchar *arg_name)
Packit ae235b
{
Packit ae235b
  g_dbus_method_invocation_return_error (invocation,
Packit ae235b
					 G_DBUS_ERROR, G_DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN,
Packit ae235b
					 "selinux context not supported");
Packit ae235b
  _g_freedesktop_dbus_complete_get_connection_selinux_security_context (object, invocation, "");
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
handle_get_connection_unix_process_id (_GFreedesktopDBus *object,
Packit ae235b
				       GDBusMethodInvocation *invocation,
Packit ae235b
				       const gchar *arg_name)
Packit ae235b
{
Packit ae235b
  g_dbus_method_invocation_return_error (invocation,
Packit ae235b
					 G_DBUS_ERROR, G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
Packit ae235b
					 "connection pid not supported");
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
handle_get_connection_unix_user (_GFreedesktopDBus *object,
Packit ae235b
				 GDBusMethodInvocation *invocation,
Packit ae235b
				 const gchar *arg_name)
Packit ae235b
{
Packit ae235b
  g_dbus_method_invocation_return_error (invocation,
Packit ae235b
					 G_DBUS_ERROR, G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
Packit ae235b
					 "connection user not supported");
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
handle_get_id (_GFreedesktopDBus *object,
Packit ae235b
	       GDBusMethodInvocation *invocation)
Packit ae235b
{
Packit ae235b
  GDBusDaemon *daemon = G_DBUS_DAEMON (object);
Packit ae235b
  _g_freedesktop_dbus_complete_get_id (object, invocation,
Packit ae235b
				       daemon->guid);
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
handle_get_name_owner (_GFreedesktopDBus *object,
Packit ae235b
		       GDBusMethodInvocation *invocation,
Packit ae235b
		       const gchar *arg_name)
Packit ae235b
{
Packit ae235b
  GDBusDaemon *daemon = G_DBUS_DAEMON (object);
Packit ae235b
  Name *name;
Packit ae235b
Packit ae235b
  if (strcmp (arg_name, DBUS_SERVICE_NAME) == 0)
Packit ae235b
    {
Packit ae235b
      _g_freedesktop_dbus_complete_get_name_owner (object, invocation, DBUS_SERVICE_NAME);
Packit ae235b
      return TRUE;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  if (arg_name[0] == ':')
Packit ae235b
    {
Packit ae235b
      if (g_hash_table_lookup (daemon->clients, arg_name) == NULL)
Packit ae235b
	g_dbus_method_invocation_return_error (invocation,
Packit ae235b
					       G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER,
Packit ae235b
					       "Could not get owner of name '%s': no such name", arg_name);
Packit ae235b
      else
Packit ae235b
	_g_freedesktop_dbus_complete_get_name_owner (object, invocation, arg_name);
Packit ae235b
      return TRUE;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  name = name_lookup (daemon, arg_name);
Packit ae235b
  if (name == NULL || name->owner == NULL)
Packit ae235b
    {
Packit ae235b
      g_dbus_method_invocation_return_error (invocation,
Packit ae235b
					     G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER,
Packit ae235b
					     "Could not get owner of name '%s': no such name", arg_name);
Packit ae235b
      return TRUE;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  _g_freedesktop_dbus_complete_get_name_owner (object, invocation, name->owner->client->id);
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
handle_hello (_GFreedesktopDBus *object,
Packit ae235b
	      GDBusMethodInvocation *invocation)
Packit ae235b
{
Packit ae235b
  Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
Packit ae235b
  _g_freedesktop_dbus_complete_hello (object, invocation, client->id);
Packit ae235b
Packit ae235b
  g_dbus_connection_emit_signal (client->connection,
Packit ae235b
				 NULL, "/org/freedesktop/DBus",
Packit ae235b
				 "org.freedesktop.DBus", "NameAcquired",
Packit ae235b
				 g_variant_new ("(s)",
Packit ae235b
						client->id), NULL);
Packit ae235b
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
handle_list_activatable_names (_GFreedesktopDBus *object,
Packit ae235b
			       GDBusMethodInvocation *invocation)
Packit ae235b
{
Packit ae235b
  const char *names[] = { NULL };
Packit ae235b
Packit ae235b
  _g_freedesktop_dbus_complete_list_activatable_names (object,
Packit ae235b
						       invocation,
Packit ae235b
						       names);
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
handle_list_names (_GFreedesktopDBus *object,
Packit ae235b
		   GDBusMethodInvocation *invocation)
Packit ae235b
{
Packit ae235b
  GDBusDaemon *daemon = G_DBUS_DAEMON (object);
Packit ae235b
  GPtrArray *array;
Packit ae235b
  GList *clients, *names, *l;
Packit ae235b
Packit ae235b
  array = g_ptr_array_new ();
Packit ae235b
Packit ae235b
  clients = g_hash_table_get_values (daemon->clients);
Packit ae235b
  for (l = clients; l != NULL; l = l->next)
Packit ae235b
    {
Packit ae235b
      Client *client = l->data;
Packit ae235b
Packit ae235b
      g_ptr_array_add (array, client->id);
Packit ae235b
    }
Packit ae235b
Packit ae235b
  g_list_free (clients);
Packit ae235b
Packit ae235b
  names = g_hash_table_get_values (daemon->names);
Packit ae235b
  for (l = names; l != NULL; l = l->next)
Packit ae235b
    {
Packit ae235b
      Name *name = l->data;
Packit ae235b
Packit ae235b
      g_ptr_array_add (array, name->name);
Packit ae235b
    }
Packit ae235b
Packit ae235b
  g_list_free (names);
Packit ae235b
Packit ae235b
  g_ptr_array_add (array, NULL);
Packit ae235b
Packit ae235b
  _g_freedesktop_dbus_complete_list_names (object,
Packit ae235b
					   invocation,
Packit ae235b
					   (const gchar * const*)array->pdata);
Packit ae235b
  g_ptr_array_free (array, TRUE);
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
handle_list_queued_owners (_GFreedesktopDBus *object,
Packit ae235b
			   GDBusMethodInvocation *invocation,
Packit ae235b
			   const gchar *arg_name)
Packit ae235b
{
Packit ae235b
  GDBusDaemon *daemon = G_DBUS_DAEMON (object);
Packit ae235b
  GPtrArray *array;
Packit ae235b
  Name *name;
Packit ae235b
  GList *l;
Packit ae235b
Packit ae235b
  array = g_ptr_array_new ();
Packit ae235b
Packit ae235b
  name = name_lookup (daemon, arg_name);
Packit ae235b
  if (name && name->owner)
Packit ae235b
    {
Packit ae235b
      for (l = name->queue; l != NULL; l = l->next)
Packit ae235b
	{
Packit ae235b
	  Client *client = l->data;
Packit ae235b
Packit ae235b
	  g_ptr_array_add (array, client->id);
Packit ae235b
	}
Packit ae235b
    }
Packit ae235b
Packit ae235b
  g_ptr_array_add (array, NULL);
Packit ae235b
Packit ae235b
  _g_freedesktop_dbus_complete_list_queued_owners (object,
Packit ae235b
						   invocation,
Packit ae235b
						   (const gchar * const*)array->pdata);
Packit ae235b
  g_ptr_array_free (array, TRUE);
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
handle_name_has_owner (_GFreedesktopDBus *object,
Packit ae235b
		       GDBusMethodInvocation *invocation,
Packit ae235b
		       const gchar *arg_name)
Packit ae235b
{
Packit ae235b
  GDBusDaemon *daemon = G_DBUS_DAEMON (object);
Packit ae235b
  Name *name;
Packit ae235b
  Client *client;
Packit ae235b
Packit ae235b
  name = name_lookup (daemon, arg_name);
Packit ae235b
  client = g_hash_table_lookup (daemon->clients, arg_name);
Packit ae235b
Packit ae235b
  _g_freedesktop_dbus_complete_name_has_owner (object, invocation,
Packit ae235b
					       name != NULL || client != NULL);
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
handle_release_name (_GFreedesktopDBus *object,
Packit ae235b
		     GDBusMethodInvocation *invocation,
Packit ae235b
		     const gchar *arg_name)
Packit ae235b
{
Packit ae235b
  Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
Packit ae235b
  GDBusDaemon *daemon = G_DBUS_DAEMON (object);
Packit ae235b
  Name *name;
Packit ae235b
  guint32 result;
Packit ae235b
Packit ae235b
  if (!g_dbus_is_name (arg_name))
Packit ae235b
    {
Packit ae235b
      g_dbus_method_invocation_return_error (invocation,
Packit ae235b
					     G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
Packit ae235b
					     "Given bus name \"%s\" is not valid", arg_name);
Packit ae235b
      return TRUE;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  if (*arg_name == ':')
Packit ae235b
    {
Packit ae235b
      g_dbus_method_invocation_return_error (invocation,
Packit ae235b
					     G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
Packit ae235b
					     "Cannot release a service starting with ':' such as \"%s\"", arg_name);
Packit ae235b
      return TRUE;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  if (strcmp (arg_name, DBUS_SERVICE_NAME) == 0)
Packit ae235b
    {
Packit ae235b
      g_dbus_method_invocation_return_error (invocation,
Packit ae235b
					     G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
Packit ae235b
					     "Cannot release a service named " DBUS_SERVICE_NAME ", because that is owned by the bus");
Packit ae235b
      return TRUE;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  name = name_lookup (daemon, arg_name);
Packit ae235b
Packit ae235b
  if (name == NULL)
Packit ae235b
    result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
Packit ae235b
  else if (name->owner && name->owner->client == client)
Packit ae235b
    {
Packit ae235b
      name_release_owner (name);
Packit ae235b
      result = DBUS_RELEASE_NAME_REPLY_RELEASED;
Packit ae235b
    }
Packit ae235b
  else if (name_unqueue_owner (name, client))
Packit ae235b
    result = DBUS_RELEASE_NAME_REPLY_RELEASED;
Packit ae235b
  else
Packit ae235b
    result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
Packit ae235b
Packit ae235b
  _g_freedesktop_dbus_complete_release_name (object, invocation, result);
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
handle_reload_config (_GFreedesktopDBus *object,
Packit ae235b
		      GDBusMethodInvocation *invocation)
Packit ae235b
{
Packit ae235b
  _g_freedesktop_dbus_complete_reload_config (object, invocation);
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
handle_update_activation_environment (_GFreedesktopDBus *object,
Packit ae235b
				      GDBusMethodInvocation *invocation,
Packit ae235b
				      GVariant *arg_environment)
Packit ae235b
{
Packit ae235b
  g_dbus_method_invocation_return_error (invocation,
Packit ae235b
					 G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
Packit ae235b
					 "UpdateActivationEnvironment not implemented");
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
handle_remove_match (_GFreedesktopDBus *object,
Packit ae235b
		     GDBusMethodInvocation *invocation,
Packit ae235b
		     const gchar *arg_rule)
Packit ae235b
{
Packit ae235b
  Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
Packit ae235b
  Match *match, *other_match;
Packit ae235b
  GList *l;
Packit ae235b
Packit ae235b
  match = match_new (arg_rule);
Packit ae235b
Packit ae235b
  if (match == NULL)
Packit ae235b
    g_dbus_method_invocation_return_error (invocation,
Packit ae235b
					   G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_INVALID,
Packit ae235b
					   "Invalid rule: %s", arg_rule);
Packit ae235b
  else
Packit ae235b
    {
Packit ae235b
      for (l = client->matches; l != NULL; l = l->next)
Packit ae235b
	{
Packit ae235b
	  other_match = l->data;
Packit ae235b
	  if (match_equal (match, other_match))
Packit ae235b
	    {
Packit ae235b
	      match_free (other_match);
Packit ae235b
	      client->matches = g_list_delete_link (client->matches, l);
Packit ae235b
	      break;
Packit ae235b
	    }
Packit ae235b
	}
Packit ae235b
Packit ae235b
      if (l == NULL)
Packit ae235b
	g_dbus_method_invocation_return_error (invocation,
Packit ae235b
					       G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_NOT_FOUND,
Packit ae235b
					       "The given match rule wasn't found and can't be removed");
Packit ae235b
      else
Packit ae235b
	_g_freedesktop_dbus_complete_remove_match (object, invocation);
Packit ae235b
    }
Packit ae235b
Packit ae235b
  match_free (match);
Packit ae235b
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
handle_request_name (_GFreedesktopDBus *object,
Packit ae235b
		     GDBusMethodInvocation *invocation,
Packit ae235b
		     const gchar *arg_name,
Packit ae235b
		     guint flags)
Packit ae235b
{
Packit ae235b
  Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
Packit ae235b
  GDBusDaemon *daemon = G_DBUS_DAEMON (object);
Packit ae235b
  Name *name;
Packit ae235b
  NameOwner *owner;
Packit ae235b
  guint32 result;
Packit ae235b
Packit ae235b
  if (!g_dbus_is_name (arg_name))
Packit ae235b
    {
Packit ae235b
      g_dbus_method_invocation_return_error (invocation,
Packit ae235b
					     G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
Packit ae235b
					     "Requested bus name \"%s\" is not valid", arg_name);
Packit ae235b
      return TRUE;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  if (*arg_name == ':')
Packit ae235b
    {
Packit ae235b
      g_dbus_method_invocation_return_error (invocation,
Packit ae235b
					     G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
Packit ae235b
					     "Cannot acquire a service starting with ':' such as \"%s\"", arg_name);
Packit ae235b
      return TRUE;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  if (strcmp (arg_name, DBUS_SERVICE_NAME) == 0)
Packit ae235b
    {
Packit ae235b
      g_dbus_method_invocation_return_error (invocation,
Packit ae235b
					     G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
Packit ae235b
					     "Cannot acquire a service named " DBUS_SERVICE_NAME ", because that is reserved");
Packit ae235b
      return TRUE;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  name = name_ensure (daemon, arg_name);
Packit ae235b
  if (name->owner == NULL)
Packit ae235b
    {
Packit ae235b
      owner = name_owner_new (client, flags);
Packit ae235b
      name_replace_owner (name, owner);
Packit ae235b
Packit ae235b
      result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
Packit ae235b
    }
Packit ae235b
  else if (name->owner && name->owner->client == client)
Packit ae235b
    {
Packit ae235b
      name->owner->flags = flags;
Packit ae235b
      result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
Packit ae235b
    }
Packit ae235b
  else if ((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
Packit ae235b
	   (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) ||
Packit ae235b
	    !(name->owner->flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT)))
Packit ae235b
    {
Packit ae235b
      /* Unqueue if queued */
Packit ae235b
      name_unqueue_owner (name, client);
Packit ae235b
      result = DBUS_REQUEST_NAME_REPLY_EXISTS;
Packit ae235b
    }
Packit ae235b
  else if (!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
Packit ae235b
	   (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) ||
Packit ae235b
	    !(name->owner->flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT)))
Packit ae235b
    {
Packit ae235b
      /* Queue the connection */
Packit ae235b
      owner = name_owner_new (client, flags);
Packit ae235b
      name_queue_owner (name, owner);
Packit ae235b
      result = DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
Packit ae235b
    }
Packit ae235b
  else
Packit ae235b
    {
Packit ae235b
      /* Replace the current owner */
Packit ae235b
Packit ae235b
      owner = name_owner_new (client, flags);
Packit ae235b
      name_replace_owner (name, owner);
Packit ae235b
Packit ae235b
      result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  name_unref (name);
Packit ae235b
Packit ae235b
  _g_freedesktop_dbus_complete_request_name (object, invocation, result);
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
handle_start_service_by_name (_GFreedesktopDBus *object,
Packit ae235b
			      GDBusMethodInvocation *invocation,
Packit ae235b
			      const gchar *arg_name,
Packit ae235b
			      guint arg_flags)
Packit ae235b
{
Packit ae235b
  GDBusDaemon *daemon = G_DBUS_DAEMON (object);
Packit ae235b
  Name *name;
Packit ae235b
Packit ae235b
  name = name_lookup (daemon, arg_name);
Packit ae235b
  if (name)
Packit ae235b
    _g_freedesktop_dbus_complete_start_service_by_name (object, invocation,
Packit ae235b
							DBUS_START_REPLY_ALREADY_RUNNING);
Packit ae235b
  else
Packit ae235b
    g_dbus_method_invocation_return_error (invocation,
Packit ae235b
					   G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN,
Packit ae235b
					   "No support for activation for name: %s", arg_name);
Packit ae235b
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
G_GNUC_PRINTF(5, 6)
Packit ae235b
static void
Packit ae235b
return_error (Client *client, GDBusMessage *message,
Packit ae235b
	      GQuark                 domain,
Packit ae235b
	      gint                   code,
Packit ae235b
	      const gchar           *format,
Packit ae235b
	      ...)
Packit ae235b
{
Packit ae235b
  GDBusMessage *reply;
Packit ae235b
  va_list var_args;
Packit ae235b
  char *error_message;
Packit ae235b
  GError *error;
Packit ae235b
  gchar *dbus_error_name;
Packit ae235b
Packit ae235b
  va_start (var_args, format);
Packit ae235b
  error_message = g_strdup_vprintf (format, var_args);
Packit ae235b
  va_end (var_args);
Packit ae235b
Packit ae235b
  error = g_error_new_literal (domain, code, "");
Packit ae235b
  dbus_error_name = g_dbus_error_encode_gerror (error);
Packit ae235b
Packit ae235b
  reply = g_dbus_message_new_method_error_literal (message,
Packit ae235b
						   dbus_error_name,
Packit ae235b
						   error_message);
Packit ae235b
Packit ae235b
  g_error_free (error);
Packit ae235b
  g_free (dbus_error_name);
Packit ae235b
  g_free (error_message);
Packit ae235b
Packit ae235b
  if (!g_dbus_connection_send_message (client->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL))
Packit ae235b
      g_warning ("Error sending reply");
Packit ae235b
  g_object_unref (reply);
Packit ae235b
}
Packit ae235b
Packit ae235b
static GDBusMessage *
Packit ae235b
route_message (Client *source_client, GDBusMessage *message)
Packit ae235b
{
Packit ae235b
  const char *dest;
Packit ae235b
  Client *dest_client;
Packit ae235b
  GDBusDaemon *daemon;
Packit ae235b
Packit ae235b
  daemon = source_client->daemon;
Packit ae235b
Packit ae235b
  dest_client = NULL;
Packit ae235b
  dest = g_dbus_message_get_destination (message);
Packit ae235b
  if (dest != NULL && strcmp (dest, DBUS_SERVICE_NAME) != 0)
Packit ae235b
    {
Packit ae235b
      dest_client = g_hash_table_lookup (daemon->clients, dest);
Packit ae235b
Packit ae235b
      if (dest_client == NULL)
Packit ae235b
	{
Packit ae235b
	  Name *name;
Packit ae235b
	  name = name_lookup (daemon, dest);
Packit ae235b
	  if (name && name->owner)
Packit ae235b
	    dest_client = name->owner->client;
Packit ae235b
	}
Packit ae235b
Packit ae235b
      if (dest_client == NULL)
Packit ae235b
	{
Packit ae235b
	  if (g_dbus_message_get_message_type (message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL)
Packit ae235b
	    return_error (source_client, message,
Packit ae235b
			  G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN,
Packit ae235b
			  "The name %s is unknown", dest);
Packit ae235b
	}
Packit ae235b
      else
Packit ae235b
	{
Packit ae235b
	  GError *error = NULL;
Packit ae235b
Packit ae235b
	  if (!g_dbus_connection_send_message (dest_client->connection, message, G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL, NULL, &error))
Packit ae235b
	    {
Packit ae235b
	      g_warning ("Error forwarding message: %s", error->message);
Packit ae235b
	      g_error_free (error);
Packit ae235b
	    }
Packit ae235b
	}
Packit ae235b
    }
Packit ae235b
Packit ae235b
  broadcast_message (daemon, message, dest_client != NULL, TRUE, dest_client);
Packit ae235b
Packit ae235b
  /* Swallow messages not for the bus */
Packit ae235b
  if (dest == NULL || strcmp (dest, DBUS_SERVICE_NAME) != 0)
Packit ae235b
    {
Packit ae235b
      g_object_unref (message);
Packit ae235b
      message = NULL;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return message;
Packit ae235b
}
Packit ae235b
Packit ae235b
static GDBusMessage *
Packit ae235b
copy_if_locked (GDBusMessage *message)
Packit ae235b
{
Packit ae235b
  if (g_dbus_message_get_locked (message))
Packit ae235b
    {
Packit ae235b
      GDBusMessage *copy = g_dbus_message_copy (message, NULL);
Packit ae235b
      g_object_unref (message);
Packit ae235b
      message = copy;
Packit ae235b
    }
Packit ae235b
  return message;
Packit ae235b
}
Packit ae235b
Packit ae235b
static GDBusMessage *
Packit ae235b
filter_function (GDBusConnection *connection,
Packit ae235b
		 GDBusMessage    *message,
Packit ae235b
		 gboolean         incoming,
Packit ae235b
		 gpointer         user_data)
Packit ae235b
{
Packit ae235b
  Client *client = user_data;
Packit ae235b
  char *types[] = {"invalid", "method_call", "method_return", "error", "signal" };
Packit ae235b
Packit ae235b
  if (0)
Packit ae235b
    g_printerr ("%s%s %s %d(%d) sender: %s destination: %s %s %s.%s\n",
Packit ae235b
		client->id,
Packit ae235b
		incoming? "->" : "<-",
Packit ae235b
		types[g_dbus_message_get_message_type (message)],
Packit ae235b
		g_dbus_message_get_serial (message),
Packit ae235b
		g_dbus_message_get_reply_serial (message),
Packit ae235b
		g_dbus_message_get_sender (message),
Packit ae235b
		g_dbus_message_get_destination (message),
Packit ae235b
		g_dbus_message_get_path (message),
Packit ae235b
		g_dbus_message_get_interface (message),
Packit ae235b
		g_dbus_message_get_member (message));
Packit ae235b
Packit ae235b
  if (incoming)
Packit ae235b
    {
Packit ae235b
      /* Ensure its not locked so we can set the sender */
Packit ae235b
      message = copy_if_locked (message);
Packit ae235b
      if (message == NULL)
Packit ae235b
	{
Packit ae235b
	  g_warning ("Failed to copy incoming message");
Packit ae235b
	  return NULL;
Packit ae235b
	}
Packit ae235b
      g_dbus_message_set_sender (message, client->id);
Packit ae235b
Packit ae235b
      return route_message (client, message);
Packit ae235b
    }
Packit ae235b
  else
Packit ae235b
    {
Packit ae235b
      if (g_dbus_message_get_sender (message) == NULL)
Packit ae235b
	{
Packit ae235b
	  message = copy_if_locked (message);
Packit ae235b
	  g_dbus_message_set_sender (message, DBUS_SERVICE_NAME);
Packit ae235b
	}
Packit ae235b
      if (g_dbus_message_get_destination (message) == NULL)
Packit ae235b
	{
Packit ae235b
	  message = copy_if_locked (message);
Packit ae235b
	  g_dbus_message_set_destination (message, client->id);
Packit ae235b
	}
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return message;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
on_new_connection (GDBusServer *server,
Packit ae235b
		   GDBusConnection *connection,
Packit ae235b
		   gpointer user_data)
Packit ae235b
{
Packit ae235b
  GDBusDaemon *daemon = user_data;
Packit ae235b
Packit ae235b
  g_dbus_connection_set_exit_on_close (connection, FALSE);
Packit ae235b
Packit ae235b
  if (daemon->timeout)
Packit ae235b
    {
Packit ae235b
      g_source_remove (daemon->timeout);
Packit ae235b
      daemon->timeout = 0;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  client_new (daemon, connection);
Packit ae235b
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
on_authorize_authenticated_peer (GDBusAuthObserver *observer,
Packit ae235b
				 GIOStream         *stream,
Packit ae235b
				 GCredentials      *credentials,
Packit ae235b
				 gpointer           user_data)
Packit ae235b
{
Packit ae235b
  gboolean authorized = TRUE;
Packit ae235b
Packit ae235b
  if (credentials != NULL)
Packit ae235b
    {
Packit ae235b
      GCredentials *own_credentials;
Packit ae235b
Packit ae235b
      own_credentials = g_credentials_new ();
Packit ae235b
      authorized = g_credentials_is_same_user (credentials, own_credentials, NULL);
Packit ae235b
      g_object_unref (own_credentials);
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return authorized;
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_dbus_daemon_finalize (GObject *object)
Packit ae235b
{
Packit ae235b
  GDBusDaemon *daemon = G_DBUS_DAEMON (object);
Packit ae235b
  GList *clients, *l;
Packit ae235b
Packit ae235b
  if (daemon->timeout)
Packit ae235b
    g_source_remove (daemon->timeout);
Packit ae235b
Packit ae235b
  clients = g_hash_table_get_values (daemon->clients);
Packit ae235b
  for (l = clients; l != NULL; l = l->next)
Packit ae235b
    client_free (l->data);
Packit ae235b
  g_list_free (clients);
Packit ae235b
Packit ae235b
  g_assert (g_hash_table_size (daemon->clients) == 0);
Packit ae235b
  g_assert (g_hash_table_size (daemon->names) == 0);
Packit ae235b
Packit ae235b
  g_hash_table_destroy (daemon->clients);
Packit ae235b
  g_hash_table_destroy (daemon->names);
Packit ae235b
Packit ae235b
  g_object_unref (daemon->server);
Packit ae235b
Packit ae235b
  if (daemon->tmpdir)
Packit ae235b
    {
Packit ae235b
      g_rmdir (daemon->tmpdir);
Packit ae235b
      g_free (daemon->tmpdir);
Packit ae235b
    }
Packit ae235b
Packit ae235b
  g_free (daemon->guid);
Packit ae235b
  g_free (daemon->address);
Packit ae235b
Packit ae235b
  G_OBJECT_CLASS (g_dbus_daemon_parent_class)->finalize (object);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_dbus_daemon_init (GDBusDaemon *daemon)
Packit ae235b
{
Packit ae235b
  daemon->next_major_id = 1;
Packit ae235b
  daemon->clients = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
Packit ae235b
  daemon->names = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
Packit ae235b
  daemon->guid = g_dbus_generate_guid ();
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
initable_init (GInitable     *initable,
Packit ae235b
	       GCancellable  *cancellable,
Packit ae235b
	       GError       **error)
Packit ae235b
{
Packit ae235b
  GDBusDaemon *daemon = G_DBUS_DAEMON (initable);
Packit ae235b
  GDBusAuthObserver *observer;
Packit ae235b
  GDBusServerFlags flags;
Packit ae235b
Packit ae235b
  flags = G_DBUS_SERVER_FLAGS_NONE;
Packit ae235b
  if (daemon->address == NULL)
Packit ae235b
    {
Packit ae235b
#ifdef G_OS_UNIX
Packit ae235b
      if (g_unix_socket_address_abstract_names_supported ())
Packit ae235b
	daemon->address = g_strdup ("unix:tmpdir=/tmp/gdbus-daemon");
Packit ae235b
      else
Packit ae235b
	{
Packit ae235b
	  daemon->tmpdir = g_dir_make_tmp ("gdbus-daemon-XXXXXX", NULL);
Packit ae235b
	  daemon->address = g_strdup_printf ("unix:tmpdir=%s", daemon->tmpdir);
Packit ae235b
	}
Packit ae235b
#else
Packit ae235b
      daemon->address = g_strdup ("nonce-tcp:");
Packit ae235b
      flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS;
Packit ae235b
#endif
Packit ae235b
    }
Packit ae235b
Packit ae235b
  observer = g_dbus_auth_observer_new ();
Packit ae235b
  daemon->server = g_dbus_server_new_sync (daemon->address,
Packit ae235b
					   flags,
Packit ae235b
					   daemon->guid,
Packit ae235b
					   observer,
Packit ae235b
					   cancellable,
Packit ae235b
					   error);
Packit ae235b
  if (daemon->server == NULL)
Packit ae235b
    {
Packit ae235b
      g_object_unref (observer);
Packit ae235b
      return FALSE;
Packit ae235b
    }
Packit ae235b
Packit ae235b
Packit ae235b
  g_dbus_server_start (daemon->server);
Packit ae235b
Packit ae235b
  g_signal_connect (daemon->server, "new-connection",
Packit ae235b
		    G_CALLBACK (on_new_connection),
Packit ae235b
		    daemon);
Packit ae235b
  g_signal_connect (observer,
Packit ae235b
		    "authorize-authenticated-peer",
Packit ae235b
		    G_CALLBACK (on_authorize_authenticated_peer),
Packit ae235b
		    daemon);
Packit ae235b
Packit ae235b
  g_object_unref (observer);
Packit ae235b
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_dbus_daemon_set_property (GObject      *object,
Packit ae235b
			    guint         prop_id,
Packit ae235b
			    const GValue *value,
Packit ae235b
			    GParamSpec   *pspec)
Packit ae235b
{
Packit ae235b
  GDBusDaemon *daemon = G_DBUS_DAEMON (object);
Packit ae235b
Packit ae235b
  switch (prop_id)
Packit ae235b
    {
Packit ae235b
    case PROP_ADDRESS:
Packit ae235b
      g_free (daemon->address);
Packit ae235b
      daemon->address = g_value_dup_string (value);
Packit ae235b
      break;
Packit ae235b
Packit ae235b
    default:
Packit ae235b
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit ae235b
    }
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_dbus_daemon_get_property (GObject    *object,
Packit ae235b
			    guint       prop_id,
Packit ae235b
			    GValue     *value,
Packit ae235b
			    GParamSpec *pspec)
Packit ae235b
{
Packit ae235b
  GDBusDaemon *daemon = G_DBUS_DAEMON (object);
Packit ae235b
Packit ae235b
  switch (prop_id)
Packit ae235b
    {
Packit ae235b
      case PROP_ADDRESS:
Packit ae235b
	g_value_set_string (value, daemon->address);
Packit ae235b
	break;
Packit ae235b
Packit ae235b
    default:
Packit ae235b
	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit ae235b
    }
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_dbus_daemon_class_init (GDBusDaemonClass *klass)
Packit ae235b
{
Packit ae235b
  GObjectClass *gobject_class;
Packit ae235b
Packit ae235b
  gobject_class = G_OBJECT_CLASS (klass);
Packit ae235b
  gobject_class->finalize = g_dbus_daemon_finalize;
Packit ae235b
  gobject_class->set_property = g_dbus_daemon_set_property;
Packit ae235b
  gobject_class->get_property = g_dbus_daemon_get_property;
Packit ae235b
Packit ae235b
  g_dbus_daemon_signals[SIGNAL_IDLE_TIMEOUT] =
Packit ae235b
    g_signal_new (I_("idle-timeout"),
Packit ae235b
		  G_TYPE_DBUS_DAEMON,
Packit ae235b
		  G_SIGNAL_RUN_LAST,
Packit ae235b
		  0,
Packit ae235b
		  NULL, NULL,
Packit ae235b
		  g_cclosure_marshal_VOID__VOID,
Packit ae235b
		  G_TYPE_NONE, 0);
Packit ae235b
Packit ae235b
  g_object_class_install_property (gobject_class,
Packit ae235b
				   PROP_ADDRESS,
Packit ae235b
				   g_param_spec_string ("address",
Packit ae235b
							"Bus Address",
Packit ae235b
							"The address the bus should use",
Packit ae235b
							NULL,
Packit ae235b
							G_PARAM_READWRITE |
Packit ae235b
							G_PARAM_CONSTRUCT_ONLY |
Packit ae235b
							G_PARAM_STATIC_STRINGS));
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_dbus_daemon_iface_init (_GFreedesktopDBusIface *iface)
Packit ae235b
{
Packit ae235b
  iface->handle_add_match = handle_add_match;
Packit ae235b
  iface->handle_get_connection_selinux_security_context = handle_get_connection_selinux_security_context;
Packit ae235b
  iface->handle_get_connection_unix_process_id = handle_get_connection_unix_process_id;
Packit ae235b
  iface->handle_get_connection_unix_user = handle_get_connection_unix_user;
Packit ae235b
  iface->handle_get_id = handle_get_id;
Packit ae235b
  iface->handle_get_name_owner = handle_get_name_owner;
Packit ae235b
  iface->handle_hello = handle_hello;
Packit ae235b
  iface->handle_list_activatable_names = handle_list_activatable_names;
Packit ae235b
  iface->handle_list_names = handle_list_names;
Packit ae235b
  iface->handle_list_queued_owners = handle_list_queued_owners;
Packit ae235b
  iface->handle_name_has_owner = handle_name_has_owner;
Packit ae235b
  iface->handle_release_name = handle_release_name;
Packit ae235b
  iface->handle_reload_config = handle_reload_config;
Packit ae235b
  iface->handle_update_activation_environment = handle_update_activation_environment;
Packit ae235b
  iface->handle_remove_match = handle_remove_match;
Packit ae235b
  iface->handle_request_name = handle_request_name;
Packit ae235b
  iface->handle_start_service_by_name = handle_start_service_by_name;
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
initable_iface_init (GInitableIface *initable_iface)
Packit ae235b
{
Packit ae235b
  initable_iface->init = initable_init;
Packit ae235b
}
Packit ae235b
Packit ae235b
GDBusDaemon *
Packit ae235b
_g_dbus_daemon_new (const char *address,
Packit ae235b
		    GCancellable *cancellable,
Packit ae235b
		    GError **error)
Packit ae235b
{
Packit ae235b
  return g_initable_new (G_TYPE_DBUS_DAEMON,
Packit ae235b
			 cancellable,
Packit ae235b
			 error,
Packit ae235b
			 "address", address,
Packit ae235b
			 NULL);
Packit ae235b
}
Packit ae235b
Packit ae235b
const char *
Packit ae235b
_g_dbus_daemon_get_address (GDBusDaemon *daemon)
Packit ae235b
{
Packit ae235b
  return g_dbus_server_get_client_address (daemon->server);
Packit ae235b
}