• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  #include "config.h"
2  
3  #include <string.h>
4  #include <stdlib.h>
5  
6  #include <gstdio.h>
7  #include <gio/gio.h>
8  #include <gio/gunixsocketaddress.h>
9  #include "gdbusdaemon.h"
10  #include "glibintl.h"
11  
12  #include "gdbus-daemon-generated.h"
13  
14  #define DBUS_SERVICE_NAME  "org.freedesktop.DBus"
15  
16  /* Owner flags */
17  #define DBUS_NAME_FLAG_ALLOW_REPLACEMENT 0x1 /**< Allow another service to become the primary owner if requested */
18  #define DBUS_NAME_FLAG_REPLACE_EXISTING  0x2 /**< Request to replace the current primary owner */
19  #define DBUS_NAME_FLAG_DO_NOT_QUEUE      0x4 /**< If we can not become the primary owner do not place us in the queue */
20  
21  /* Replies to request for a name */
22  #define DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER  1 /**< Service has become the primary owner of the requested name */
23  #define DBUS_REQUEST_NAME_REPLY_IN_QUEUE       2 /**< Service could not become the primary owner and has been placed in the queue */
24  #define DBUS_REQUEST_NAME_REPLY_EXISTS         3 /**< Service is already in the queue */
25  #define DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER  4 /**< Service is already the primary owner */
26  
27  /* Replies to releasing a name */
28  #define DBUS_RELEASE_NAME_REPLY_RELEASED        1 /**< Service was released from the given name */
29  #define DBUS_RELEASE_NAME_REPLY_NON_EXISTENT    2 /**< The given name does not exist on the bus */
30  #define DBUS_RELEASE_NAME_REPLY_NOT_OWNER       3 /**< Service is not an owner of the given name */
31  
32  /* Replies to service starts */
33  #define DBUS_START_REPLY_SUCCESS         1 /**< Service was auto started */
34  #define DBUS_START_REPLY_ALREADY_RUNNING 2 /**< Service was already running */
35  
36  #define IDLE_TIMEOUT_MSEC 3000
37  
38  struct _GDBusDaemon
39  {
40    _GFreedesktopDBusSkeleton parent_instance;
41  
42    gchar *address;
43    guint timeout;
44    gchar *tmpdir;
45    GDBusServer *server;
46    gchar *guid;
47    GHashTable *clients;
48    GHashTable *names;
49    guint32 next_major_id;
50    guint32 next_minor_id;
51  };
52  
53  struct _GDBusDaemonClass
54  {
55    _GFreedesktopDBusSkeletonClass parent_class;
56  };
57  
58  enum {
59    PROP_0,
60    PROP_ADDRESS,
61  };
62  
63  enum
64  {
65    SIGNAL_IDLE_TIMEOUT,
66    NR_SIGNALS
67  };
68  
69  static guint g_dbus_daemon_signals[NR_SIGNALS];
70  
71  
72  static void initable_iface_init      (GInitableIface         *initable_iface);
73  static void g_dbus_daemon_iface_init (_GFreedesktopDBusIface *iface);
74  
75  #define g_dbus_daemon_get_type _g_dbus_daemon_get_type
76  G_DEFINE_TYPE_WITH_CODE (GDBusDaemon, g_dbus_daemon, _G_TYPE_FREEDESKTOP_DBUS_SKELETON,
77  			 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)
78  			 G_IMPLEMENT_INTERFACE (_G_TYPE_FREEDESKTOP_DBUS, g_dbus_daemon_iface_init))
79  
80  typedef struct {
81    GDBusDaemon *daemon;
82    char *id;
83    GDBusConnection *connection;
84    GList *matches;
85  } Client;
86  
87  typedef struct {
88    Client *client;
89    guint32 flags;
90  } NameOwner;
91  
92  typedef struct {
93    int refcount;
94  
95    char *name;
96    GDBusDaemon *daemon;
97  
98    NameOwner *owner;
99    GList *queue;
100  } Name;
101  
102  enum {
103    MATCH_ELEMENT_TYPE,
104    MATCH_ELEMENT_SENDER,
105    MATCH_ELEMENT_INTERFACE,
106    MATCH_ELEMENT_MEMBER,
107    MATCH_ELEMENT_PATH,
108    MATCH_ELEMENT_PATH_NAMESPACE,
109    MATCH_ELEMENT_DESTINATION,
110    MATCH_ELEMENT_ARG0NAMESPACE,
111    MATCH_ELEMENT_EAVESDROP,
112    MATCH_ELEMENT_ARGN,
113    MATCH_ELEMENT_ARGNPATH,
114  };
115  
116  typedef struct {
117    guint16 type;
118    guint16 arg;
119    char *value;
120  } MatchElement;
121  
122  typedef struct {
123    gboolean eavesdrop;
124    GDBusMessageType type;
125    int n_elements;
126    MatchElement *elements;
127  } Match;
128  
129  static GDBusMessage *filter_function   (GDBusConnection *connection,
130  					GDBusMessage    *message,
131  					gboolean         incoming,
132  					gpointer         user_data);
133  static void          connection_closed (GDBusConnection *connection,
134  					gboolean         remote_peer_vanished,
135  					GError          *error,
136  					Client          *client);
137  
138  static NameOwner *
name_owner_new(Client * client,guint32 flags)139  name_owner_new (Client *client, guint32 flags)
140  {
141    NameOwner *owner;
142  
143    owner = g_new0 (NameOwner, 1);
144    owner->client = client;
145    owner->flags = flags;
146    return owner;
147  }
148  
149  static void
name_owner_free(NameOwner * owner)150  name_owner_free (NameOwner *owner)
151  {
152    g_free (owner);
153  }
154  
155  static Name *
name_new(GDBusDaemon * daemon,const char * str)156  name_new (GDBusDaemon *daemon, const char *str)
157  {
158    Name *name;
159  
160    name = g_new0 (Name, 1);
161    name->refcount = 1;
162    name->daemon = daemon;
163    name->name = g_strdup (str);
164  
165    g_hash_table_insert (daemon->names, name->name, name);
166  
167    return name;
168  }
169  
170  static Name *
name_ref(Name * name)171  name_ref (Name *name)
172  {
173    g_assert (name->refcount > 0);
174    name->refcount++;
175    return name;
176  }
177  
178  static void
name_unref(Name * name)179  name_unref (Name *name)
180  {
181    g_assert (name->refcount > 0);
182    if (--name->refcount == 0)
183      {
184        g_hash_table_remove (name->daemon->names, name->name);
185        g_free (name->name);
186        g_free (name);
187      }
188  }
189  
190  static Name *
name_ensure(GDBusDaemon * daemon,const char * str)191  name_ensure (GDBusDaemon *daemon, const char *str)
192  {
193    Name *name;
194  
195    name = g_hash_table_lookup (daemon->names, str);
196  
197    if (name != NULL)
198      return name_ref (name);
199    return name_new (daemon, str);
200  }
201  
202  static Name *
name_lookup(GDBusDaemon * daemon,const char * str)203  name_lookup (GDBusDaemon *daemon, const char *str)
204  {
205    return g_hash_table_lookup (daemon->names, str);
206  }
207  
208  static gboolean
is_key(const char * key_start,const char * key_end,const char * value)209  is_key (const char *key_start, const char *key_end, const char *value)
210  {
211    gsize len = strlen (value);
212  
213    g_assert (key_end >= key_start);
214    if (len != (gsize) (key_end - key_start))
215      return FALSE;
216  
217    return strncmp (key_start, value, len) == 0;
218  }
219  
220  static gboolean
parse_key(MatchElement * element,const char * key_start,const char * key_end)221  parse_key (MatchElement *element, const char *key_start, const char *key_end)
222  {
223    gboolean res = TRUE;
224  
225    if (is_key (key_start, key_end, "type"))
226      {
227        element->type = MATCH_ELEMENT_TYPE;
228      }
229    else if (is_key (key_start, key_end, "sender"))
230      {
231        element->type = MATCH_ELEMENT_SENDER;
232      }
233    else if (is_key (key_start, key_end, "interface"))
234      {
235        element->type = MATCH_ELEMENT_INTERFACE;
236      }
237    else if (is_key (key_start, key_end, "member"))
238      {
239        element->type = MATCH_ELEMENT_MEMBER;
240      }
241    else if (is_key (key_start, key_end, "path"))
242      {
243        element->type = MATCH_ELEMENT_PATH;
244      }
245    else if (is_key (key_start, key_end, "path_namespace"))
246      {
247        element->type = MATCH_ELEMENT_PATH_NAMESPACE;
248      }
249    else if (is_key (key_start, key_end, "destination"))
250      {
251        element->type = MATCH_ELEMENT_DESTINATION;
252      }
253    else if (is_key (key_start, key_end, "arg0namespace"))
254      {
255        element->type = MATCH_ELEMENT_ARG0NAMESPACE;
256      }
257    else if (is_key (key_start, key_end, "eavesdrop"))
258      {
259        element->type = MATCH_ELEMENT_EAVESDROP;
260      }
261    else if (key_end - key_start > 3 && is_key (key_start, key_start + 3, "arg"))
262      {
263        const char *digits = key_start + 3;
264        const char *end_digits = digits;
265  
266        while (end_digits < key_end && g_ascii_isdigit (*end_digits))
267  	end_digits++;
268  
269        if (end_digits == key_end) /* argN */
270  	{
271  	  element->type = MATCH_ELEMENT_ARGN;
272  	  element->arg = atoi (digits);
273  	}
274        else if (is_key (end_digits, key_end, "path")) /* argNpath */
275  	{
276  	  element->type = MATCH_ELEMENT_ARGNPATH;
277  	  element->arg = atoi (digits);
278  	}
279        else
280  	res = FALSE;
281      }
282    else
283      res = FALSE;
284  
285    return res;
286  }
287  
288  static const char *
parse_value(MatchElement * element,const char * s)289  parse_value (MatchElement *element, const char *s)
290  {
291    char quote_char;
292    GString *value;
293  
294    value = g_string_new ("");
295  
296    quote_char = 0;
297  
298    for (;*s; s++)
299      {
300        if (quote_char == 0)
301  	{
302  	  switch (*s)
303  	    {
304  	    case '\'':
305  	      quote_char = '\'';
306  	      break;
307  
308  	    case ',':
309  	      s++;
310  	      goto out;
311  
312  	    case '\\':
313  	      quote_char = '\\';
314  	      break;
315  
316  	    default:
317  	      g_string_append_c (value, *s);
318  	      break;
319  	    }
320  	}
321        else if (quote_char == '\\')
322  	{
323  	  /* \ only counts as an escape if escaping a quote mark */
324  	  if (*s != '\'')
325  	    g_string_append_c (value, '\\');
326  
327  	  g_string_append_c (value, *s);
328  	  quote_char = 0;
329  	}
330        else /* quote_char == ' */
331  	{
332  	  if (*s == '\'')
333  	    quote_char = 0;
334  	  else
335  	    g_string_append_c (value, *s);
336  	}
337      }
338  
339   out:
340  
341    if (quote_char == '\\')
342      g_string_append_c (value, '\\');
343    else if (quote_char == '\'')
344      {
345        g_string_free (value, TRUE);
346        return NULL;
347      }
348  
349    element->value = g_string_free (value, FALSE);
350    return s;
351  }
352  
353  static Match *
match_new(const char * str)354  match_new (const char *str)
355  {
356    Match *match;
357    GArray *elements;
358    const char *p;
359    const char *key_start;
360    const char *key_end;
361    MatchElement element;
362    gboolean eavesdrop;
363    GDBusMessageType type;
364    gsize i;
365  
366    eavesdrop = FALSE;
367    type = G_DBUS_MESSAGE_TYPE_INVALID;
368    elements = g_array_new (TRUE, TRUE, sizeof (MatchElement));
369  
370    p = str;
371  
372    while (*p != 0)
373      {
374        memset (&element, 0, sizeof (element));
375  
376        /* Skip initial whitespace */
377        while (*p && g_ascii_isspace (*p))
378  	p++;
379  
380        key_start = p;
381  
382        /* Read non-whitespace non-equals chars */
383        while (*p && *p != '=' && !g_ascii_isspace (*p))
384  	p++;
385  
386        key_end = p;
387  
388        /* Skip any whitespace after key */
389        while (*p && g_ascii_isspace (*p))
390  	p++;
391  
392        if (key_start == key_end)
393  	continue; /* Allow trailing whitespace */
394  
395        if (*p != '=')
396  	goto error;
397  
398        ++p;
399  
400        if (!parse_key (&element, key_start, key_end))
401  	goto error;
402  
403        p = parse_value (&element, p);
404        if (p == NULL)
405  	goto error;
406  
407        if (element.type == MATCH_ELEMENT_EAVESDROP)
408  	{
409  	  if (strcmp (element.value, "true") == 0)
410  	    eavesdrop = TRUE;
411  	  else if (strcmp (element.value, "false") == 0)
412  	    eavesdrop = FALSE;
413  	  else
414  	    {
415  	      g_free (element.value);
416  	      goto error;
417  	    }
418  	  g_free (element.value);
419  	}
420        else if (element.type == MATCH_ELEMENT_TYPE)
421  	{
422  	  if (strcmp (element.value, "signal") == 0)
423  	    type = G_DBUS_MESSAGE_TYPE_SIGNAL;
424  	  else if (strcmp (element.value, "method_call") == 0)
425  	    type = G_DBUS_MESSAGE_TYPE_METHOD_CALL;
426  	  else if (strcmp (element.value, "method_return") == 0)
427  	    type = G_DBUS_MESSAGE_TYPE_METHOD_RETURN;
428  	  else if (strcmp (element.value, "error") == 0)
429  	    type = G_DBUS_MESSAGE_TYPE_ERROR;
430  	  else
431  	    {
432  	      g_free (element.value);
433  	      goto error;
434  	    }
435  	  g_free (element.value);
436  	}
437        else
438  	g_array_append_val (elements, element);
439      }
440  
441    match = g_new0 (Match, 1);
442    match->n_elements = elements->len;
443    match->elements = (MatchElement *)g_array_free (elements, FALSE);
444    match->eavesdrop = eavesdrop;
445    match->type = type;
446  
447    return match;
448  
449   error:
450    for (i = 0; i < elements->len; i++)
451      g_free (g_array_index (elements, MatchElement, i).value);
452    g_array_free (elements, TRUE);
453    return NULL;
454  }
455  
456  static void
match_free(Match * match)457  match_free (Match *match)
458  {
459    int i;
460    for (i = 0; i < match->n_elements; i++)
461      g_free (match->elements[i].value);
462    g_free (match->elements);
463    g_free (match);
464  }
465  
466  static gboolean
match_equal(Match * a,Match * b)467  match_equal (Match *a, Match *b)
468  {
469    int i;
470  
471    if (a->eavesdrop != b->eavesdrop)
472      return FALSE;
473    if (a->type != b->type)
474      return FALSE;
475   if (a->n_elements != b->n_elements)
476      return FALSE;
477    for (i = 0; i < a->n_elements; i++)
478      {
479        if (a->elements[i].type != b->elements[i].type ||
480  	  a->elements[i].arg != b->elements[i].arg ||
481  	  strcmp (a->elements[i].value, b->elements[i].value) != 0)
482  	return FALSE;
483      }
484    return TRUE;
485  }
486  
487  static const gchar *
message_get_argN(GDBusMessage * message,int n,gboolean allow_path)488  message_get_argN (GDBusMessage *message, int n, gboolean allow_path)
489  {
490    const gchar *ret;
491    GVariant *body;
492  
493    ret = NULL;
494  
495    body = g_dbus_message_get_body (message);
496  
497    if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE_TUPLE))
498      {
499        GVariant *item;
500        item = g_variant_get_child_value (body, n);
501        if (g_variant_is_of_type (item, G_VARIANT_TYPE_STRING) ||
502  	  (allow_path && g_variant_is_of_type (item, G_VARIANT_TYPE_OBJECT_PATH)))
503  	ret = g_variant_get_string (item, NULL);
504        g_variant_unref (item);
505      }
506  
507    return ret;
508  }
509  
510  enum {
511    CHECK_TYPE_STRING,
512    CHECK_TYPE_NAME,
513    CHECK_TYPE_PATH_PREFIX,
514    CHECK_TYPE_PATH_RELATED,
515    CHECK_TYPE_NAMESPACE_PREFIX
516  };
517  
518  static gboolean
match_matches(GDBusDaemon * daemon,Match * match,GDBusMessage * message,gboolean has_destination)519  match_matches (GDBusDaemon *daemon,
520  	       Match *match, GDBusMessage *message,
521  	       gboolean has_destination)
522  {
523    MatchElement *element;
524    Name *name;
525    int i, len, len2;
526    const char *value;
527    int check_type;
528  
529    if (has_destination && !match->eavesdrop)
530      return FALSE;
531  
532    if (match->type != G_DBUS_MESSAGE_TYPE_INVALID &&
533        g_dbus_message_get_message_type (message) != match->type)
534      return FALSE;
535  
536    for (i = 0; i < match->n_elements; i++)
537      {
538        element = &match->elements[i];
539        check_type = CHECK_TYPE_STRING;
540        switch (element->type)
541  	{
542  	case MATCH_ELEMENT_SENDER:
543  	  check_type = CHECK_TYPE_NAME;
544  	  value = g_dbus_message_get_sender (message);
545  	  if (value == NULL)
546  	    value = DBUS_SERVICE_NAME;
547  	  break;
548  	case MATCH_ELEMENT_DESTINATION:
549  	  check_type = CHECK_TYPE_NAME;
550  	  value = g_dbus_message_get_destination (message);
551  	  break;
552  	case MATCH_ELEMENT_INTERFACE:
553  	  value = g_dbus_message_get_interface (message);
554  	  break;
555  	case MATCH_ELEMENT_MEMBER:
556  	  value = g_dbus_message_get_member (message);
557  	  break;
558  	case MATCH_ELEMENT_PATH:
559  	  value = g_dbus_message_get_path (message);
560  	  break;
561  	case MATCH_ELEMENT_PATH_NAMESPACE:
562  	  check_type = CHECK_TYPE_PATH_PREFIX;
563  	  value = g_dbus_message_get_path (message);
564  	  break;
565  	case MATCH_ELEMENT_ARG0NAMESPACE:
566  	  check_type = CHECK_TYPE_NAMESPACE_PREFIX;
567  	  value = message_get_argN (message, 0, FALSE);
568  	  break;
569  	case MATCH_ELEMENT_ARGN:
570  	  value = message_get_argN (message, element->arg, FALSE);
571  	  break;
572  	case MATCH_ELEMENT_ARGNPATH:
573  	  check_type = CHECK_TYPE_PATH_RELATED;
574  	  value = message_get_argN (message, element->arg, TRUE);
575  	  break;
576  	default:
577  	case MATCH_ELEMENT_TYPE:
578  	case MATCH_ELEMENT_EAVESDROP:
579  	  g_assert_not_reached ();
580  	}
581  
582        if (value == NULL)
583  	return FALSE;
584  
585        switch (check_type)
586  	{
587  	case CHECK_TYPE_STRING:
588  	  if (strcmp (element->value, value) != 0)
589  	    return FALSE;
590  	  break;
591  	case CHECK_TYPE_NAME:
592  	  name = name_lookup (daemon, element->value);
593  	  if (name != NULL && name->owner != NULL)
594  	    {
595  	      if (strcmp (name->owner->client->id, value) != 0)
596  		return FALSE;
597  	    }
598  	  else if (strcmp (element->value, value) != 0)
599  	    return FALSE;
600  	  break;
601  	case CHECK_TYPE_PATH_PREFIX:
602  	  len = strlen (element->value);
603  
604  	  /* Make sure to handle the case of element->value == '/'. */
605  	  if (len == 1)
606  	    break;
607  
608  	  /* Fail if there's no prefix match, or if the prefix match doesn't
609  	   * finish at the end of or at a separator in the @value. */
610  	  if (!g_str_has_prefix (value, element->value))
611  	    return FALSE;
612  	  if (value[len] != 0 && value[len] != '/')
613  	    return FALSE;
614  
615  	  break;
616  	case CHECK_TYPE_PATH_RELATED:
617  	  len = strlen (element->value);
618  	  len2 = strlen (value);
619  
620  	  if (!(strcmp (value, element->value) == 0 ||
621  		(len2 > 0 && value[len2-1] == '/' && g_str_has_prefix (element->value, value)) ||
622  		(len > 0 && element->value[len-1] == '/' && g_str_has_prefix (value, element->value))))
623  	    return FALSE;
624  	  break;
625  	case CHECK_TYPE_NAMESPACE_PREFIX:
626  	  len = strlen (element->value);
627  	  if (!(g_str_has_prefix (value, element->value) &&
628  		(value[len] == 0 || value[len] == '.')))
629  	    return FALSE;
630  	  break;
631  	default:
632  	  g_assert_not_reached ();
633  	}
634      }
635  
636    return TRUE;
637  }
638  
639  static void
broadcast_message(GDBusDaemon * daemon,GDBusMessage * message,gboolean has_destination,gboolean preserve_serial,Client * not_to)640  broadcast_message (GDBusDaemon *daemon,
641  		   GDBusMessage *message,
642  		   gboolean has_destination,
643  		   gboolean preserve_serial,
644  		   Client *not_to)
645  {
646    GList *clients, *l, *ll;
647    GDBusMessage *copy;
648  
649    clients = g_hash_table_get_values (daemon->clients);
650    for (l = clients; l != NULL; l = l->next)
651      {
652        Client *client = l->data;
653  
654        if (client == not_to)
655  	continue;
656  
657        for (ll = client->matches; ll != NULL; ll = ll->next)
658  	{
659  	  Match *match = ll->data;
660  
661  	  if (match_matches (daemon, match, message, has_destination))
662  	    break;
663  	}
664  
665        if (ll != NULL)
666  	{
667  	  copy = g_dbus_message_copy (message, NULL);
668  	  if (copy)
669  	    {
670  	      g_dbus_connection_send_message (client->connection, copy,
671  					      preserve_serial?G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL:0, NULL, NULL);
672  	      g_object_unref (copy);
673  	    }
674  	}
675      }
676  
677    g_list_free (clients);
678  }
679  
680  static void
send_name_owner_changed(GDBusDaemon * daemon,const char * name,const char * old_owner,const char * new_owner)681  send_name_owner_changed (GDBusDaemon *daemon,
682  			 const char *name,
683  			 const char *old_owner,
684  			 const char *new_owner)
685  {
686    GDBusMessage *signal_message;
687  
688    signal_message = g_dbus_message_new_signal ("/org/freedesktop/DBus",
689  					      "org.freedesktop.DBus",
690  					      "NameOwnerChanged");
691    g_dbus_message_set_body (signal_message,
692  			   g_variant_new ("(sss)",
693  					  name,
694  					  old_owner ? old_owner : "",
695  					  new_owner ? new_owner : ""));
696  
697    broadcast_message (daemon, signal_message, FALSE, FALSE, NULL);
698    g_object_unref (signal_message);
699  
700  }
701  
702  static gboolean
name_unqueue_owner(Name * name,Client * client)703  name_unqueue_owner (Name *name, Client *client)
704  {
705    GList *l;
706  
707    for (l = name->queue; l != NULL; l = l->next)
708      {
709        NameOwner *other = l->data;
710  
711        if (other->client == client)
712  	{
713  	  name->queue = g_list_delete_link (name->queue, l);
714  	  name_unref (name);
715  	  name_owner_free (other);
716  	  return TRUE;
717  	}
718      }
719  
720    return FALSE;
721  }
722  
723  static void
name_replace_owner(Name * name,NameOwner * owner)724  name_replace_owner (Name *name, NameOwner *owner)
725  {
726    GDBusDaemon *daemon = name->daemon;
727    NameOwner *old_owner;
728    char *old_name = NULL, *new_name = NULL;
729    Client *new_client = NULL;
730  
731    if (owner)
732      new_client = owner->client;
733  
734    name_ref (name);
735  
736    old_owner = name->owner;
737    if (old_owner)
738      {
739        Client *old_client = old_owner->client;
740  
741        g_assert (old_owner->client != new_client);
742  
743        g_dbus_connection_emit_signal (old_client->connection,
744  				     NULL, "/org/freedesktop/DBus",
745  				     "org.freedesktop.DBus", "NameLost",
746  				     g_variant_new ("(s)",
747  						    name->name), NULL);
748  
749        old_name = g_strdup (old_client->id);
750        if (old_owner->flags & DBUS_NAME_FLAG_DO_NOT_QUEUE)
751  	{
752  	  name_unref (name);
753  	  name_owner_free (old_owner);
754  	}
755        else
756  	name->queue = g_list_prepend (name->queue, old_owner);
757      }
758  
759    name->owner = owner;
760    if (owner)
761      {
762        name_unqueue_owner (name, owner->client);
763        name_ref (name);
764        new_name = new_client->id;
765  
766        g_dbus_connection_emit_signal (new_client->connection,
767  				     NULL, "/org/freedesktop/DBus",
768  				     "org.freedesktop.DBus", "NameAcquired",
769  				     g_variant_new ("(s)",
770  						    name->name), NULL);
771      }
772  
773    send_name_owner_changed (daemon, name->name, old_name, new_name);
774  
775    g_free (old_name);
776  
777    name_unref (name);
778  }
779  
780  static void
name_release_owner(Name * name)781  name_release_owner (Name *name)
782  {
783    NameOwner *next_owner = NULL;
784  
785    name_ref (name);
786  
787    /* Will someone else take over? */
788    if (name->queue)
789      {
790        next_owner = name->queue->data;
791        name_unref (name);
792        name->queue = g_list_delete_link (name->queue, name->queue);
793      }
794  
795    name->owner->flags |= DBUS_NAME_FLAG_DO_NOT_QUEUE;
796    name_replace_owner (name, next_owner);
797  
798    name_unref (name);
799  }
800  
801  static void
name_queue_owner(Name * name,NameOwner * owner)802  name_queue_owner (Name *name, NameOwner *owner)
803  {
804    GList *l;
805  
806    for (l = name->queue; l != NULL; l = l->next)
807      {
808        NameOwner *other = l->data;
809  
810        if (other->client == owner->client)
811  	{
812  	  other->flags = owner->flags;
813  	  name_owner_free (owner);
814  	  return;
815  	}
816      }
817  
818    name->queue = g_list_append (name->queue, owner);
819    name_ref (name);
820  }
821  
822  static Client *
client_new(GDBusDaemon * daemon,GDBusConnection * connection)823  client_new (GDBusDaemon *daemon, GDBusConnection *connection)
824  {
825    Client *client;
826    GError *error = NULL;
827  
828    client = g_new0 (Client, 1);
829    client->daemon = daemon;
830    client->id = g_strdup_printf (":%d.%d", daemon->next_major_id, daemon->next_minor_id);
831    client->connection = g_object_ref (connection);
832  
833    if (daemon->next_minor_id == G_MAXUINT32)
834      {
835        daemon->next_minor_id = 0;
836        daemon->next_major_id++;
837      }
838    else
839      daemon->next_minor_id++;
840  
841    g_object_set_data (G_OBJECT (connection), "client", client);
842    g_hash_table_insert (daemon->clients, client->id, client);
843  
844    g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (daemon), connection,
845  				    "/org/freedesktop/DBus", &error);
846    g_assert_no_error (error);
847  
848    g_signal_connect (connection, "closed", G_CALLBACK (connection_closed), client);
849    g_dbus_connection_add_filter (connection,
850  				filter_function,
851  				client, NULL);
852  
853    send_name_owner_changed (daemon, client->id, NULL, client->id);
854  
855    return client;
856  }
857  
858  static void
client_free(Client * client)859  client_free (Client *client)
860  {
861    GDBusDaemon *daemon = client->daemon;
862    GList *l, *names;
863  
864    g_dbus_interface_skeleton_unexport_from_connection (G_DBUS_INTERFACE_SKELETON (daemon),
865  						      client->connection);
866  
867    g_hash_table_remove (daemon->clients, client->id);
868  
869    names = g_hash_table_get_values (daemon->names);
870    for (l = names; l != NULL; l = l->next)
871      {
872        Name *name = l->data;
873  
874        name_ref (name);
875  
876        if (name->owner && name->owner->client == client)
877  	name_release_owner (name);
878  
879        name_unqueue_owner (name, client);
880  
881        name_unref (name);
882      }
883    g_list_free (names);
884  
885    send_name_owner_changed (daemon, client->id, client->id, NULL);
886  
887    g_object_unref (client->connection);
888  
889    for (l = client->matches; l != NULL; l = l->next)
890      match_free (l->data);
891    g_list_free (client->matches);
892  
893    g_free (client->id);
894    g_free (client);
895  }
896  
897  static gboolean
idle_timeout_cb(gpointer user_data)898  idle_timeout_cb (gpointer user_data)
899  {
900    GDBusDaemon *daemon = user_data;
901  
902    daemon->timeout = 0;
903  
904    g_signal_emit (daemon,
905  		 g_dbus_daemon_signals[SIGNAL_IDLE_TIMEOUT],
906  		 0);
907  
908    return G_SOURCE_REMOVE;
909  }
910  
911  static void
connection_closed(GDBusConnection * connection,gboolean remote_peer_vanished,GError * error,Client * client)912  connection_closed (GDBusConnection *connection,
913  		   gboolean remote_peer_vanished,
914  		   GError *error,
915  		   Client *client)
916  {
917    GDBusDaemon *daemon = client->daemon;
918  
919    client_free (client);
920  
921    if (g_hash_table_size (daemon->clients) == 0)
922      daemon->timeout = g_timeout_add (IDLE_TIMEOUT_MSEC,
923  				     idle_timeout_cb,
924  				     daemon);
925  }
926  
927  static gboolean
handle_add_match(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_rule)928  handle_add_match (_GFreedesktopDBus *object,
929  		  GDBusMethodInvocation *invocation,
930  		  const gchar *arg_rule)
931  {
932    Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
933    Match *match;
934  
935    match = match_new (arg_rule);
936  
937    if (match == NULL)
938      g_dbus_method_invocation_return_error (invocation,
939  					   G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_INVALID,
940  					   "Invalid rule: %s", arg_rule);
941    else
942      {
943        client->matches = g_list_prepend (client->matches, match);
944        _g_freedesktop_dbus_complete_add_match (object, invocation);
945      }
946    return TRUE;
947  }
948  
949  static gboolean
handle_get_connection_selinux_security_context(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name)950  handle_get_connection_selinux_security_context (_GFreedesktopDBus *object,
951  						GDBusMethodInvocation *invocation,
952  						const gchar *arg_name)
953  {
954    g_dbus_method_invocation_return_error (invocation,
955  					 G_DBUS_ERROR, G_DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN,
956  					 "selinux context not supported");
957    _g_freedesktop_dbus_complete_get_connection_selinux_security_context (object, invocation, "");
958    return TRUE;
959  }
960  
961  static gboolean
handle_get_connection_unix_process_id(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name)962  handle_get_connection_unix_process_id (_GFreedesktopDBus *object,
963  				       GDBusMethodInvocation *invocation,
964  				       const gchar *arg_name)
965  {
966    g_dbus_method_invocation_return_error (invocation,
967  					 G_DBUS_ERROR, G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
968  					 "connection pid not supported");
969    return TRUE;
970  }
971  
972  static gboolean
handle_get_connection_unix_user(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name)973  handle_get_connection_unix_user (_GFreedesktopDBus *object,
974  				 GDBusMethodInvocation *invocation,
975  				 const gchar *arg_name)
976  {
977    g_dbus_method_invocation_return_error (invocation,
978  					 G_DBUS_ERROR, G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
979  					 "connection user not supported");
980    return TRUE;
981  }
982  
983  static gboolean
handle_get_id(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation)984  handle_get_id (_GFreedesktopDBus *object,
985  	       GDBusMethodInvocation *invocation)
986  {
987    GDBusDaemon *daemon = G_DBUS_DAEMON (object);
988    _g_freedesktop_dbus_complete_get_id (object, invocation,
989  				       daemon->guid);
990    return TRUE;
991  }
992  
993  static gboolean
handle_get_name_owner(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name)994  handle_get_name_owner (_GFreedesktopDBus *object,
995  		       GDBusMethodInvocation *invocation,
996  		       const gchar *arg_name)
997  {
998    GDBusDaemon *daemon = G_DBUS_DAEMON (object);
999    Name *name;
1000  
1001    if (strcmp (arg_name, DBUS_SERVICE_NAME) == 0)
1002      {
1003        _g_freedesktop_dbus_complete_get_name_owner (object, invocation, DBUS_SERVICE_NAME);
1004        return TRUE;
1005      }
1006  
1007    if (arg_name[0] == ':')
1008      {
1009        if (g_hash_table_lookup (daemon->clients, arg_name) == NULL)
1010  	g_dbus_method_invocation_return_error (invocation,
1011  					       G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER,
1012  					       "Could not get owner of name '%s': no such name", arg_name);
1013        else
1014  	_g_freedesktop_dbus_complete_get_name_owner (object, invocation, arg_name);
1015        return TRUE;
1016      }
1017  
1018    name = name_lookup (daemon, arg_name);
1019    if (name == NULL || name->owner == NULL)
1020      {
1021        g_dbus_method_invocation_return_error (invocation,
1022  					     G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER,
1023  					     "Could not get owner of name '%s': no such name", arg_name);
1024        return TRUE;
1025      }
1026  
1027    _g_freedesktop_dbus_complete_get_name_owner (object, invocation, name->owner->client->id);
1028    return TRUE;
1029  }
1030  
1031  static gboolean
handle_hello(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation)1032  handle_hello (_GFreedesktopDBus *object,
1033  	      GDBusMethodInvocation *invocation)
1034  {
1035    Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
1036    _g_freedesktop_dbus_complete_hello (object, invocation, client->id);
1037  
1038    g_dbus_connection_emit_signal (client->connection,
1039  				 NULL, "/org/freedesktop/DBus",
1040  				 "org.freedesktop.DBus", "NameAcquired",
1041  				 g_variant_new ("(s)",
1042  						client->id), NULL);
1043  
1044    return TRUE;
1045  }
1046  
1047  static gboolean
handle_list_activatable_names(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation)1048  handle_list_activatable_names (_GFreedesktopDBus *object,
1049  			       GDBusMethodInvocation *invocation)
1050  {
1051    const char *names[] = { NULL };
1052  
1053    _g_freedesktop_dbus_complete_list_activatable_names (object,
1054  						       invocation,
1055  						       names);
1056    return TRUE;
1057  }
1058  
1059  static gboolean
handle_list_names(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation)1060  handle_list_names (_GFreedesktopDBus *object,
1061  		   GDBusMethodInvocation *invocation)
1062  {
1063    GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1064    GPtrArray *array;
1065    GList *clients, *names, *l;
1066  
1067    array = g_ptr_array_new ();
1068  
1069    clients = g_hash_table_get_values (daemon->clients);
1070    for (l = clients; l != NULL; l = l->next)
1071      {
1072        Client *client = l->data;
1073  
1074        g_ptr_array_add (array, client->id);
1075      }
1076  
1077    g_list_free (clients);
1078  
1079    names = g_hash_table_get_values (daemon->names);
1080    for (l = names; l != NULL; l = l->next)
1081      {
1082        Name *name = l->data;
1083  
1084        g_ptr_array_add (array, name->name);
1085      }
1086  
1087    g_list_free (names);
1088  
1089    g_ptr_array_add (array, NULL);
1090  
1091    _g_freedesktop_dbus_complete_list_names (object,
1092  					   invocation,
1093  					   (const gchar * const*)array->pdata);
1094    g_ptr_array_free (array, TRUE);
1095    return TRUE;
1096  }
1097  
1098  static gboolean
handle_list_queued_owners(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name)1099  handle_list_queued_owners (_GFreedesktopDBus *object,
1100  			   GDBusMethodInvocation *invocation,
1101  			   const gchar *arg_name)
1102  {
1103    GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1104    GPtrArray *array;
1105    Name *name;
1106    GList *l;
1107  
1108    array = g_ptr_array_new ();
1109  
1110    name = name_lookup (daemon, arg_name);
1111    if (name && name->owner)
1112      {
1113        for (l = name->queue; l != NULL; l = l->next)
1114  	{
1115  	  Client *client = l->data;
1116  
1117  	  g_ptr_array_add (array, client->id);
1118  	}
1119      }
1120  
1121    g_ptr_array_add (array, NULL);
1122  
1123    _g_freedesktop_dbus_complete_list_queued_owners (object,
1124  						   invocation,
1125  						   (const gchar * const*)array->pdata);
1126    g_ptr_array_free (array, TRUE);
1127    return TRUE;
1128  }
1129  
1130  static gboolean
handle_name_has_owner(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name)1131  handle_name_has_owner (_GFreedesktopDBus *object,
1132  		       GDBusMethodInvocation *invocation,
1133  		       const gchar *arg_name)
1134  {
1135    GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1136    Name *name;
1137    Client *client;
1138  
1139    name = name_lookup (daemon, arg_name);
1140    client = g_hash_table_lookup (daemon->clients, arg_name);
1141  
1142    _g_freedesktop_dbus_complete_name_has_owner (object, invocation,
1143  					       name != NULL || client != NULL);
1144    return TRUE;
1145  }
1146  
1147  static gboolean
handle_release_name(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name)1148  handle_release_name (_GFreedesktopDBus *object,
1149  		     GDBusMethodInvocation *invocation,
1150  		     const gchar *arg_name)
1151  {
1152    Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
1153    GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1154    Name *name;
1155    guint32 result;
1156  
1157    if (!g_dbus_is_name (arg_name))
1158      {
1159        g_dbus_method_invocation_return_error (invocation,
1160  					     G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
1161  					     "Given bus name \"%s\" is not valid", arg_name);
1162        return TRUE;
1163      }
1164  
1165    if (*arg_name == ':')
1166      {
1167        g_dbus_method_invocation_return_error (invocation,
1168  					     G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
1169  					     "Cannot release a service starting with ':' such as \"%s\"", arg_name);
1170        return TRUE;
1171      }
1172  
1173    if (strcmp (arg_name, DBUS_SERVICE_NAME) == 0)
1174      {
1175        g_dbus_method_invocation_return_error (invocation,
1176  					     G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
1177  					     "Cannot release a service named " DBUS_SERVICE_NAME ", because that is owned by the bus");
1178        return TRUE;
1179      }
1180  
1181    name = name_lookup (daemon, arg_name);
1182  
1183    if (name == NULL)
1184      result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
1185    else if (name->owner && name->owner->client == client)
1186      {
1187        name_release_owner (name);
1188        result = DBUS_RELEASE_NAME_REPLY_RELEASED;
1189      }
1190    else if (name_unqueue_owner (name, client))
1191      result = DBUS_RELEASE_NAME_REPLY_RELEASED;
1192    else
1193      result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
1194  
1195    _g_freedesktop_dbus_complete_release_name (object, invocation, result);
1196    return TRUE;
1197  }
1198  
1199  static gboolean
handle_reload_config(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation)1200  handle_reload_config (_GFreedesktopDBus *object,
1201  		      GDBusMethodInvocation *invocation)
1202  {
1203    _g_freedesktop_dbus_complete_reload_config (object, invocation);
1204    return TRUE;
1205  }
1206  
1207  static gboolean
handle_update_activation_environment(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,GVariant * arg_environment)1208  handle_update_activation_environment (_GFreedesktopDBus *object,
1209  				      GDBusMethodInvocation *invocation,
1210  				      GVariant *arg_environment)
1211  {
1212    g_dbus_method_invocation_return_error (invocation,
1213  					 G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1214  					 "UpdateActivationEnvironment not implemented");
1215    return TRUE;
1216  }
1217  
1218  static gboolean
handle_remove_match(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_rule)1219  handle_remove_match (_GFreedesktopDBus *object,
1220  		     GDBusMethodInvocation *invocation,
1221  		     const gchar *arg_rule)
1222  {
1223    Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
1224    Match *match, *other_match;
1225    GList *l;
1226  
1227    match = match_new (arg_rule);
1228  
1229    if (match == NULL)
1230      g_dbus_method_invocation_return_error (invocation,
1231  					   G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_INVALID,
1232  					   "Invalid rule: %s", arg_rule);
1233    else
1234      {
1235        for (l = client->matches; l != NULL; l = l->next)
1236  	{
1237  	  other_match = l->data;
1238  	  if (match_equal (match, other_match))
1239  	    {
1240  	      match_free (other_match);
1241  	      client->matches = g_list_delete_link (client->matches, l);
1242  	      break;
1243  	    }
1244  	}
1245  
1246        if (l == NULL)
1247  	g_dbus_method_invocation_return_error (invocation,
1248  					       G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_NOT_FOUND,
1249  					       "The given match rule wasn't found and can't be removed");
1250        else
1251  	_g_freedesktop_dbus_complete_remove_match (object, invocation);
1252      }
1253    if (match)
1254      match_free (match);
1255  
1256    return TRUE;
1257  }
1258  
1259  static gboolean
handle_request_name(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name,guint flags)1260  handle_request_name (_GFreedesktopDBus *object,
1261  		     GDBusMethodInvocation *invocation,
1262  		     const gchar *arg_name,
1263  		     guint flags)
1264  {
1265    Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
1266    GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1267    Name *name;
1268    NameOwner *owner;
1269    guint32 result;
1270  
1271    if (!g_dbus_is_name (arg_name))
1272      {
1273        g_dbus_method_invocation_return_error (invocation,
1274  					     G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
1275  					     "Requested bus name \"%s\" is not valid", arg_name);
1276        return TRUE;
1277      }
1278  
1279    if (*arg_name == ':')
1280      {
1281        g_dbus_method_invocation_return_error (invocation,
1282  					     G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
1283  					     "Cannot acquire a service starting with ':' such as \"%s\"", arg_name);
1284        return TRUE;
1285      }
1286  
1287    if (strcmp (arg_name, DBUS_SERVICE_NAME) == 0)
1288      {
1289        g_dbus_method_invocation_return_error (invocation,
1290  					     G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
1291  					     "Cannot acquire a service named " DBUS_SERVICE_NAME ", because that is reserved");
1292        return TRUE;
1293      }
1294  
1295    name = name_ensure (daemon, arg_name);
1296    if (name->owner == NULL)
1297      {
1298        owner = name_owner_new (client, flags);
1299        name_replace_owner (name, owner);
1300  
1301        result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
1302      }
1303    else if (name->owner && name->owner->client == client)
1304      {
1305        name->owner->flags = flags;
1306        result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
1307      }
1308    else if ((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
1309  	   (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) ||
1310  	    !(name->owner->flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT)))
1311      {
1312        /* Unqueue if queued */
1313        name_unqueue_owner (name, client);
1314        result = DBUS_REQUEST_NAME_REPLY_EXISTS;
1315      }
1316    else if (!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
1317  	   (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) ||
1318  	    !(name->owner->flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT)))
1319      {
1320        /* Queue the connection */
1321        owner = name_owner_new (client, flags);
1322        name_queue_owner (name, owner);
1323        result = DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
1324      }
1325    else
1326      {
1327        /* Replace the current owner */
1328  
1329        owner = name_owner_new (client, flags);
1330        name_replace_owner (name, owner);
1331  
1332        result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
1333      }
1334  
1335    name_unref (name);
1336  
1337    _g_freedesktop_dbus_complete_request_name (object, invocation, result);
1338    return TRUE;
1339  }
1340  
1341  static gboolean
handle_start_service_by_name(_GFreedesktopDBus * object,GDBusMethodInvocation * invocation,const gchar * arg_name,guint arg_flags)1342  handle_start_service_by_name (_GFreedesktopDBus *object,
1343  			      GDBusMethodInvocation *invocation,
1344  			      const gchar *arg_name,
1345  			      guint arg_flags)
1346  {
1347    GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1348    Name *name;
1349  
1350    name = name_lookup (daemon, arg_name);
1351    if (name)
1352      _g_freedesktop_dbus_complete_start_service_by_name (object, invocation,
1353  							DBUS_START_REPLY_ALREADY_RUNNING);
1354    else
1355      g_dbus_method_invocation_return_error (invocation,
1356  					   G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN,
1357  					   "No support for activation for name: %s", arg_name);
1358  
1359    return TRUE;
1360  }
1361  
1362  G_GNUC_PRINTF(5, 6)
1363  static void
return_error(Client * client,GDBusMessage * message,GQuark domain,gint code,const gchar * format,...)1364  return_error (Client *client, GDBusMessage *message,
1365  	      GQuark                 domain,
1366  	      gint                   code,
1367  	      const gchar           *format,
1368  	      ...)
1369  {
1370    GDBusMessage *reply;
1371    va_list var_args;
1372    char *error_message;
1373    GError *error;
1374    gchar *dbus_error_name;
1375  
1376    va_start (var_args, format);
1377    error_message = g_strdup_vprintf (format, var_args);
1378    va_end (var_args);
1379  
1380    error = g_error_new_literal (domain, code, "");
1381    dbus_error_name = g_dbus_error_encode_gerror (error);
1382  
1383    reply = g_dbus_message_new_method_error_literal (message,
1384  						   dbus_error_name,
1385  						   error_message);
1386  
1387    g_error_free (error);
1388    g_free (dbus_error_name);
1389    g_free (error_message);
1390  
1391    if (!g_dbus_connection_send_message (client->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL))
1392        g_warning ("Error sending reply");
1393    g_object_unref (reply);
1394  }
1395  
1396  static GDBusMessage *
route_message(Client * source_client,GDBusMessage * message)1397  route_message (Client *source_client, GDBusMessage *message)
1398  {
1399    const char *dest;
1400    Client *dest_client;
1401    GDBusDaemon *daemon;
1402  
1403    daemon = source_client->daemon;
1404  
1405    dest_client = NULL;
1406    dest = g_dbus_message_get_destination (message);
1407    if (dest != NULL && strcmp (dest, DBUS_SERVICE_NAME) != 0)
1408      {
1409        dest_client = g_hash_table_lookup (daemon->clients, dest);
1410  
1411        if (dest_client == NULL)
1412  	{
1413  	  Name *name;
1414  	  name = name_lookup (daemon, dest);
1415  	  if (name && name->owner)
1416  	    dest_client = name->owner->client;
1417  	}
1418  
1419        if (dest_client == NULL)
1420  	{
1421  	  if (g_dbus_message_get_message_type (message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL)
1422  	    return_error (source_client, message,
1423  			  G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN,
1424  			  "The name %s is unknown", dest);
1425  	}
1426        else
1427  	{
1428  	  GError *error = NULL;
1429  
1430  	  if (!g_dbus_connection_send_message (dest_client->connection, message, G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL, NULL, &error))
1431  	    {
1432  	      g_warning ("Error forwarding message: %s", error->message);
1433  	      g_error_free (error);
1434  	    }
1435  	}
1436      }
1437  
1438    broadcast_message (daemon, message, dest_client != NULL, TRUE, dest_client);
1439  
1440    /* Swallow messages not for the bus */
1441    if (dest == NULL || strcmp (dest, DBUS_SERVICE_NAME) != 0)
1442      {
1443        g_object_unref (message);
1444        message = NULL;
1445      }
1446  
1447    return message;
1448  }
1449  
1450  static GDBusMessage *
copy_if_locked(GDBusMessage * message)1451  copy_if_locked (GDBusMessage *message)
1452  {
1453    if (g_dbus_message_get_locked (message))
1454      {
1455        GDBusMessage *copy = g_dbus_message_copy (message, NULL);
1456        g_object_unref (message);
1457        message = copy;
1458      }
1459    return message;
1460  }
1461  
1462  static GDBusMessage *
filter_function(GDBusConnection * connection,GDBusMessage * message,gboolean incoming,gpointer user_data)1463  filter_function (GDBusConnection *connection,
1464  		 GDBusMessage    *message,
1465  		 gboolean         incoming,
1466  		 gpointer         user_data)
1467  {
1468    Client *client = user_data;
1469  
1470    if (0)
1471      {
1472        const char *types[] = {"invalid", "method_call", "method_return", "error", "signal" };
1473        g_printerr ("%s%s %s %d(%d) sender: %s destination: %s %s %s.%s\n",
1474  		client->id,
1475  		incoming? "->" : "<-",
1476  		types[g_dbus_message_get_message_type (message)],
1477  		g_dbus_message_get_serial (message),
1478  		g_dbus_message_get_reply_serial (message),
1479  		g_dbus_message_get_sender (message),
1480  		g_dbus_message_get_destination (message),
1481  		g_dbus_message_get_path (message),
1482  		g_dbus_message_get_interface (message),
1483  		g_dbus_message_get_member (message));
1484      }
1485  
1486    if (incoming)
1487      {
1488        /* Ensure its not locked so we can set the sender */
1489        message = copy_if_locked (message);
1490        if (message == NULL)
1491  	{
1492  	  g_warning ("Failed to copy incoming message");
1493  	  return NULL;
1494  	}
1495        g_dbus_message_set_sender (message, client->id);
1496  
1497        return route_message (client, message);
1498      }
1499    else
1500      {
1501        if (g_dbus_message_get_sender (message) == NULL ||
1502            g_dbus_message_get_destination (message) == NULL)
1503          {
1504            message = copy_if_locked (message);
1505            if (message == NULL)
1506              {
1507                g_warning ("Failed to copy outgoing message");
1508                return NULL;
1509              }
1510          }
1511  
1512        if (g_dbus_message_get_sender (message) == NULL)
1513          g_dbus_message_set_sender (message, DBUS_SERVICE_NAME);
1514        if (g_dbus_message_get_destination (message) == NULL)
1515          g_dbus_message_set_destination (message, client->id);
1516      }
1517  
1518    return message;
1519  }
1520  
1521  static gboolean
on_new_connection(GDBusServer * server,GDBusConnection * connection,gpointer user_data)1522  on_new_connection (GDBusServer *server,
1523  		   GDBusConnection *connection,
1524  		   gpointer user_data)
1525  {
1526    GDBusDaemon *daemon = user_data;
1527  
1528    g_dbus_connection_set_exit_on_close (connection, FALSE);
1529  
1530    if (daemon->timeout)
1531      {
1532        g_source_remove (daemon->timeout);
1533        daemon->timeout = 0;
1534      }
1535  
1536    client_new (daemon, connection);
1537  
1538    return TRUE;
1539  }
1540  
1541  static void
g_dbus_daemon_finalize(GObject * object)1542  g_dbus_daemon_finalize (GObject *object)
1543  {
1544    GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1545    GList *clients, *l;
1546  
1547    if (daemon->timeout)
1548      g_source_remove (daemon->timeout);
1549  
1550    clients = g_hash_table_get_values (daemon->clients);
1551    for (l = clients; l != NULL; l = l->next)
1552      client_free (l->data);
1553    g_list_free (clients);
1554  
1555    g_assert (g_hash_table_size (daemon->clients) == 0);
1556    g_assert (g_hash_table_size (daemon->names) == 0);
1557  
1558    g_hash_table_destroy (daemon->clients);
1559    g_hash_table_destroy (daemon->names);
1560  
1561    g_object_unref (daemon->server);
1562  
1563    if (daemon->tmpdir)
1564      {
1565        g_rmdir (daemon->tmpdir);
1566        g_free (daemon->tmpdir);
1567      }
1568  
1569    g_free (daemon->guid);
1570    g_free (daemon->address);
1571  
1572    G_OBJECT_CLASS (g_dbus_daemon_parent_class)->finalize (object);
1573  }
1574  
1575  static void
g_dbus_daemon_init(GDBusDaemon * daemon)1576  g_dbus_daemon_init (GDBusDaemon *daemon)
1577  {
1578    daemon->next_major_id = 1;
1579    daemon->clients = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
1580    daemon->names = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
1581    daemon->guid = g_dbus_generate_guid ();
1582  }
1583  
1584  static gboolean
initable_init(GInitable * initable,GCancellable * cancellable,GError ** error)1585  initable_init (GInitable     *initable,
1586  	       GCancellable  *cancellable,
1587  	       GError       **error)
1588  {
1589    GDBusDaemon *daemon = G_DBUS_DAEMON (initable);
1590    GDBusServerFlags flags;
1591  
1592    flags = G_DBUS_SERVER_FLAGS_NONE;
1593    if (daemon->address == NULL)
1594      {
1595  #ifdef G_OS_UNIX
1596        if (g_unix_socket_address_abstract_names_supported ())
1597  	daemon->address = g_strdup ("unix:tmpdir=/tmp/gdbus-daemon");
1598        else
1599  	{
1600  	  daemon->tmpdir = g_dir_make_tmp ("gdbus-daemon-XXXXXX", NULL);
1601  	  daemon->address = g_strdup_printf ("unix:tmpdir=%s", daemon->tmpdir);
1602  	}
1603        flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER;
1604  #else
1605        /* Don’t require authentication on Windows as that hasn’t been
1606         * implemented yet. */
1607        daemon->address = g_strdup ("nonce-tcp:");
1608        flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS;
1609  #endif
1610      }
1611  
1612    daemon->server = g_dbus_server_new_sync (daemon->address,
1613  					   flags,
1614  					   daemon->guid,
1615  					   NULL,
1616  					   cancellable,
1617  					   error);
1618    if (daemon->server == NULL)
1619      return FALSE;
1620  
1621  
1622    g_dbus_server_start (daemon->server);
1623  
1624    g_signal_connect (daemon->server, "new-connection",
1625  		    G_CALLBACK (on_new_connection),
1626  		    daemon);
1627  
1628    return TRUE;
1629  }
1630  
1631  static void
g_dbus_daemon_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)1632  g_dbus_daemon_set_property (GObject      *object,
1633  			    guint         prop_id,
1634  			    const GValue *value,
1635  			    GParamSpec   *pspec)
1636  {
1637    GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1638  
1639    switch (prop_id)
1640      {
1641      case PROP_ADDRESS:
1642        g_free (daemon->address);
1643        daemon->address = g_value_dup_string (value);
1644        break;
1645  
1646      default:
1647        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1648      }
1649  }
1650  
1651  static void
g_dbus_daemon_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1652  g_dbus_daemon_get_property (GObject    *object,
1653  			    guint       prop_id,
1654  			    GValue     *value,
1655  			    GParamSpec *pspec)
1656  {
1657    GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1658  
1659    switch (prop_id)
1660      {
1661        case PROP_ADDRESS:
1662  	g_value_set_string (value, daemon->address);
1663  	break;
1664  
1665      default:
1666  	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1667      }
1668  }
1669  
1670  static void
g_dbus_daemon_class_init(GDBusDaemonClass * klass)1671  g_dbus_daemon_class_init (GDBusDaemonClass *klass)
1672  {
1673    GObjectClass *gobject_class;
1674  
1675    gobject_class = G_OBJECT_CLASS (klass);
1676    gobject_class->finalize = g_dbus_daemon_finalize;
1677    gobject_class->set_property = g_dbus_daemon_set_property;
1678    gobject_class->get_property = g_dbus_daemon_get_property;
1679  
1680    g_dbus_daemon_signals[SIGNAL_IDLE_TIMEOUT] =
1681      g_signal_new (I_("idle-timeout"),
1682  		  G_TYPE_DBUS_DAEMON,
1683  		  G_SIGNAL_RUN_LAST,
1684  		  0,
1685  		  NULL, NULL,
1686  		  NULL,
1687  		  G_TYPE_NONE, 0);
1688  
1689    g_object_class_install_property (gobject_class,
1690  				   PROP_ADDRESS,
1691  				   g_param_spec_string ("address",
1692  							"Bus Address",
1693  							"The address the bus should use",
1694  							NULL,
1695  							G_PARAM_READWRITE |
1696  							G_PARAM_CONSTRUCT_ONLY |
1697  							G_PARAM_STATIC_STRINGS));
1698  }
1699  
1700  static void
g_dbus_daemon_iface_init(_GFreedesktopDBusIface * iface)1701  g_dbus_daemon_iface_init (_GFreedesktopDBusIface *iface)
1702  {
1703    iface->handle_add_match = handle_add_match;
1704    iface->handle_get_connection_selinux_security_context = handle_get_connection_selinux_security_context;
1705    iface->handle_get_connection_unix_process_id = handle_get_connection_unix_process_id;
1706    iface->handle_get_connection_unix_user = handle_get_connection_unix_user;
1707    iface->handle_get_id = handle_get_id;
1708    iface->handle_get_name_owner = handle_get_name_owner;
1709    iface->handle_hello = handle_hello;
1710    iface->handle_list_activatable_names = handle_list_activatable_names;
1711    iface->handle_list_names = handle_list_names;
1712    iface->handle_list_queued_owners = handle_list_queued_owners;
1713    iface->handle_name_has_owner = handle_name_has_owner;
1714    iface->handle_release_name = handle_release_name;
1715    iface->handle_reload_config = handle_reload_config;
1716    iface->handle_update_activation_environment = handle_update_activation_environment;
1717    iface->handle_remove_match = handle_remove_match;
1718    iface->handle_request_name = handle_request_name;
1719    iface->handle_start_service_by_name = handle_start_service_by_name;
1720  }
1721  
1722  static void
initable_iface_init(GInitableIface * initable_iface)1723  initable_iface_init (GInitableIface *initable_iface)
1724  {
1725    initable_iface->init = initable_init;
1726  }
1727  
1728  GDBusDaemon *
_g_dbus_daemon_new(const char * address,GCancellable * cancellable,GError ** error)1729  _g_dbus_daemon_new (const char *address,
1730  		    GCancellable *cancellable,
1731  		    GError **error)
1732  {
1733    return g_initable_new (G_TYPE_DBUS_DAEMON,
1734  			 cancellable,
1735  			 error,
1736  			 "address", address,
1737  			 NULL);
1738  }
1739  
1740  const char *
_g_dbus_daemon_get_address(GDBusDaemon * daemon)1741  _g_dbus_daemon_get_address (GDBusDaemon *daemon)
1742  {
1743    return g_dbus_server_get_client_address (daemon->server);
1744  }
1745