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