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
38struct _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
53struct _GDBusDaemonClass
54{
55 _GFreedesktopDBusSkeletonClass parent_class;
56};
57
58enum {
59 PROP_0,
60 PROP_ADDRESS,
61};
62
63enum
64{
65 SIGNAL_IDLE_TIMEOUT,
66 NR_SIGNALS
67};
68
69static guint g_dbus_daemon_signals[NR_SIGNALS];
70
71
72static void initable_iface_init (GInitableIface *initable_iface);
73static void g_dbus_daemon_iface_init (_GFreedesktopDBusIface *iface);
74
75#define g_dbus_daemon_get_type _g_dbus_daemon_get_type
76G_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
80typedef struct {
81 GDBusDaemon *daemon;
82 char *id;
83 GDBusConnection *connection;
84 GList *matches;
85} Client;
86
87typedef struct {
88 Client *client;
89 guint32 flags;
90} NameOwner;
91
92typedef struct {
93 int refcount;
94
95 char *name;
96 GDBusDaemon *daemon;
97
98 NameOwner *owner;
99 GList *queue;
100} Name;
101
102enum {
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
116typedef struct {
117 guint16 type;
118 guint16 arg;
119 char *value;
120} MatchElement;
121
122typedef struct {
123 gboolean eavesdrop;
124 GDBusMessageType type;
125 int n_elements;
126 MatchElement *elements;
127} Match;
128
129static GDBusMessage *filter_function (GDBusConnection *connection,
130 GDBusMessage *message,
131 gboolean incoming,
132 gpointer user_data);
133static void connection_closed (GDBusConnection *connection,
134 gboolean remote_peer_vanished,
135 GError *error,
136 Client *client);
137
138static NameOwner *
139name_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
149static void
150name_owner_free (NameOwner *owner)
151{
152 g_free (mem: owner);
153}
154
155static Name *
156name_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 (hash_table: daemon->names, key: name->name, value: name);
166
167 return name;
168}
169
170static Name *
171name_ref (Name *name)
172{
173 g_assert (name->refcount > 0);
174 name->refcount++;
175 return name;
176}
177
178static void
179name_unref (Name *name)
180{
181 g_assert (name->refcount > 0);
182 if (--name->refcount == 0)
183 {
184 g_hash_table_remove (hash_table: name->daemon->names, key: name->name);
185 g_free (mem: name->name);
186 g_free (mem: name);
187 }
188}
189
190static Name *
191name_ensure (GDBusDaemon *daemon, const char *str)
192{
193 Name *name;
194
195 name = g_hash_table_lookup (hash_table: daemon->names, key: str);
196
197 if (name != NULL)
198 return name_ref (name);
199 return name_new (daemon, str);
200}
201
202static Name *
203name_lookup (GDBusDaemon *daemon, const char *str)
204{
205 return g_hash_table_lookup (hash_table: daemon->names, key: str);
206}
207
208static gboolean
209is_key (const char *key_start, const char *key_end, const char *value)
210{
211 gsize len = strlen (s: value);
212
213 g_assert (key_end >= key_start);
214 if (len != (gsize) (key_end - key_start))
215 return FALSE;
216
217 return strncmp (s1: key_start, s2: value, n: len) == 0;
218}
219
220static gboolean
221parse_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, value: "type"))
226 {
227 element->type = MATCH_ELEMENT_TYPE;
228 }
229 else if (is_key (key_start, key_end, value: "sender"))
230 {
231 element->type = MATCH_ELEMENT_SENDER;
232 }
233 else if (is_key (key_start, key_end, value: "interface"))
234 {
235 element->type = MATCH_ELEMENT_INTERFACE;
236 }
237 else if (is_key (key_start, key_end, value: "member"))
238 {
239 element->type = MATCH_ELEMENT_MEMBER;
240 }
241 else if (is_key (key_start, key_end, value: "path"))
242 {
243 element->type = MATCH_ELEMENT_PATH;
244 }
245 else if (is_key (key_start, key_end, value: "path_namespace"))
246 {
247 element->type = MATCH_ELEMENT_PATH_NAMESPACE;
248 }
249 else if (is_key (key_start, key_end, value: "destination"))
250 {
251 element->type = MATCH_ELEMENT_DESTINATION;
252 }
253 else if (is_key (key_start, key_end, value: "arg0namespace"))
254 {
255 element->type = MATCH_ELEMENT_ARG0NAMESPACE;
256 }
257 else if (is_key (key_start, key_end, value: "eavesdrop"))
258 {
259 element->type = MATCH_ELEMENT_EAVESDROP;
260 }
261 else if (key_end - key_start > 3 && is_key (key_start, key_end: key_start + 3, value: "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 (nptr: digits);
273 }
274 else if (is_key (key_start: end_digits, key_end, value: "path")) /* argNpath */
275 {
276 element->type = MATCH_ELEMENT_ARGNPATH;
277 element->arg = atoi (nptr: digits);
278 }
279 else
280 res = FALSE;
281 }
282 else
283 res = FALSE;
284
285 return res;
286}
287
288static const char *
289parse_value (MatchElement *element, const char *s)
290{
291 char quote_char;
292 GString *value;
293
294 value = g_string_new (init: "");
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 (string: value, TRUE);
346 return NULL;
347 }
348
349 element->value = g_string_free (string: value, FALSE);
350 return s;
351}
352
353static Match *
354match_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, element_size: sizeof (MatchElement));
369
370 p = str;
371
372 while (*p != 0)
373 {
374 memset (s: &element, c: 0, n: 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: &element, key_start, key_end))
401 goto error;
402
403 p = parse_value (element: &element, s: p);
404 if (p == NULL)
405 goto error;
406
407 if (element.type == MATCH_ELEMENT_EAVESDROP)
408 {
409 if (strcmp (s1: element.value, s2: "true") == 0)
410 eavesdrop = TRUE;
411 else if (strcmp (s1: element.value, s2: "false") == 0)
412 eavesdrop = FALSE;
413 else
414 {
415 g_free (mem: element.value);
416 goto error;
417 }
418 g_free (mem: element.value);
419 }
420 else if (element.type == MATCH_ELEMENT_TYPE)
421 {
422 if (strcmp (s1: element.value, s2: "signal") == 0)
423 type = G_DBUS_MESSAGE_TYPE_SIGNAL;
424 else if (strcmp (s1: element.value, s2: "method_call") == 0)
425 type = G_DBUS_MESSAGE_TYPE_METHOD_CALL;
426 else if (strcmp (s1: element.value, s2: "method_return") == 0)
427 type = G_DBUS_MESSAGE_TYPE_METHOD_RETURN;
428 else if (strcmp (s1: element.value, s2: "error") == 0)
429 type = G_DBUS_MESSAGE_TYPE_ERROR;
430 else
431 {
432 g_free (mem: element.value);
433 goto error;
434 }
435 g_free (mem: 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 (array: 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 (array: elements, TRUE);
453 return NULL;
454}
455
456static void
457match_free (Match *match)
458{
459 int i;
460 for (i = 0; i < match->n_elements; i++)
461 g_free (mem: match->elements[i].value);
462 g_free (mem: match->elements);
463 g_free (mem: match);
464}
465
466static gboolean
467match_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 (s1: a->elements[i].value, s2: b->elements[i].value) != 0)
482 return FALSE;
483 }
484 return TRUE;
485}
486
487static const gchar *
488message_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 (value: body, G_VARIANT_TYPE_TUPLE))
498 {
499 GVariant *item;
500 item = g_variant_get_child_value (value: body, index_: n);
501 if (g_variant_is_of_type (value: item, G_VARIANT_TYPE_STRING) ||
502 (allow_path && g_variant_is_of_type (value: item, G_VARIANT_TYPE_OBJECT_PATH)))
503 ret = g_variant_get_string (value: item, NULL);
504 g_variant_unref (value: item);
505 }
506
507 return ret;
508}
509
510enum {
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
518static gboolean
519match_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, n: 0, FALSE);
568 break;
569 case MATCH_ELEMENT_ARGN:
570 value = message_get_argN (message, n: element->arg, FALSE);
571 break;
572 case MATCH_ELEMENT_ARGNPATH:
573 check_type = CHECK_TYPE_PATH_RELATED;
574 value = message_get_argN (message, n: 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 (s1: element->value, s2: value) != 0)
589 return FALSE;
590 break;
591 case CHECK_TYPE_NAME:
592 name = name_lookup (daemon, str: element->value);
593 if (name != NULL && name->owner != NULL)
594 {
595 if (strcmp (s1: name->owner->client->id, s2: value) != 0)
596 return FALSE;
597 }
598 else if (strcmp (s1: element->value, s2: value) != 0)
599 return FALSE;
600 break;
601 case CHECK_TYPE_PATH_PREFIX:
602 len = strlen (s: 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 (str: value, prefix: 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 (s: element->value);
618 len2 = strlen (s: value);
619
620 if (!(strcmp (s1: value, s2: element->value) == 0 ||
621 (len2 > 0 && value[len2-1] == '/' && g_str_has_prefix (str: element->value, prefix: value)) ||
622 (len > 0 && element->value[len-1] == '/' && g_str_has_prefix (str: value, prefix: element->value))))
623 return FALSE;
624 break;
625 case CHECK_TYPE_NAMESPACE_PREFIX:
626 len = strlen (s: element->value);
627 if (!(g_str_has_prefix (str: value, prefix: 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
639static void
640broadcast_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 (hash_table: 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 (connection: client->connection, message: copy,
671 flags: preserve_serial?G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL:0, NULL, NULL);
672 g_object_unref (object: copy);
673 }
674 }
675 }
676
677 g_list_free (list: clients);
678}
679
680static void
681send_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 (path: "/org/freedesktop/DBus",
689 interface_: "org.freedesktop.DBus",
690 signal: "NameOwnerChanged");
691 g_dbus_message_set_body (message: signal_message,
692 body: g_variant_new (format_string: "(sss)",
693 name,
694 old_owner ? old_owner : "",
695 new_owner ? new_owner : ""));
696
697 broadcast_message (daemon, message: signal_message, FALSE, FALSE, NULL);
698 g_object_unref (object: signal_message);
699
700}
701
702static gboolean
703name_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 (list: name->queue, link_: l);
714 name_unref (name);
715 name_owner_free (owner: other);
716 return TRUE;
717 }
718 }
719
720 return FALSE;
721}
722
723static void
724name_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 (connection: old_client->connection,
744 NULL, object_path: "/org/freedesktop/DBus",
745 interface_name: "org.freedesktop.DBus", signal_name: "NameLost",
746 parameters: g_variant_new (format_string: "(s)",
747 name->name), NULL);
748
749 old_name = g_strdup (str: old_client->id);
750 if (old_owner->flags & DBUS_NAME_FLAG_DO_NOT_QUEUE)
751 {
752 name_unref (name);
753 name_owner_free (owner: old_owner);
754 }
755 else
756 name->queue = g_list_prepend (list: name->queue, data: old_owner);
757 }
758
759 name->owner = owner;
760 if (owner)
761 {
762 name_unqueue_owner (name, client: owner->client);
763 name_ref (name);
764 new_name = new_client->id;
765
766 g_dbus_connection_emit_signal (connection: new_client->connection,
767 NULL, object_path: "/org/freedesktop/DBus",
768 interface_name: "org.freedesktop.DBus", signal_name: "NameAcquired",
769 parameters: g_variant_new (format_string: "(s)",
770 name->name), NULL);
771 }
772
773 send_name_owner_changed (daemon, name: name->name, old_owner: old_name, new_owner: new_name);
774
775 g_free (mem: old_name);
776
777 name_unref (name);
778}
779
780static void
781name_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 (list: name->queue, link_: name->queue);
793 }
794
795 name->owner->flags |= DBUS_NAME_FLAG_DO_NOT_QUEUE;
796 name_replace_owner (name, owner: next_owner);
797
798 name_unref (name);
799}
800
801static void
802name_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 (list: name->queue, data: owner);
819 name_ref (name);
820}
821
822static Client *
823client_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 (format: ":%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), key: "client", data: client);
842 g_hash_table_insert (hash_table: daemon->clients, key: client->id, value: client);
843
844 g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (daemon), connection,
845 object_path: "/org/freedesktop/DBus", error: &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 user_data: client, NULL);
852
853 send_name_owner_changed (daemon, name: client->id, NULL, new_owner: client->id);
854
855 return client;
856}
857
858static void
859client_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 connection: client->connection);
866
867 g_hash_table_remove (hash_table: daemon->clients, key: client->id);
868
869 names = g_hash_table_get_values (hash_table: 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 (list: names);
884
885 send_name_owner_changed (daemon, name: client->id, old_owner: client->id, NULL);
886
887 g_object_unref (object: client->connection);
888
889 for (l = client->matches; l != NULL; l = l->next)
890 match_free (match: l->data);
891 g_list_free (list: client->matches);
892
893 g_free (mem: client->id);
894 g_free (mem: client);
895}
896
897static gboolean
898idle_timeout_cb (gpointer user_data)
899{
900 GDBusDaemon *daemon = user_data;
901
902 daemon->timeout = 0;
903
904 g_signal_emit (instance: daemon,
905 signal_id: g_dbus_daemon_signals[SIGNAL_IDLE_TIMEOUT],
906 detail: 0);
907
908 return G_SOURCE_REMOVE;
909}
910
911static void
912connection_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 (hash_table: daemon->clients) == 0)
922 daemon->timeout = g_timeout_add (IDLE_TIMEOUT_MSEC,
923 function: idle_timeout_cb,
924 data: daemon);
925}
926
927static gboolean
928handle_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)), key: "client");
933 Match *match;
934
935 match = match_new (str: arg_rule);
936
937 if (match == NULL)
938 g_dbus_method_invocation_return_error (invocation,
939 G_DBUS_ERROR, code: G_DBUS_ERROR_MATCH_RULE_INVALID,
940 format: "Invalid rule: %s", arg_rule);
941 else
942 {
943 client->matches = g_list_prepend (list: client->matches, data: match);
944 _g_freedesktop_dbus_complete_add_match (object, invocation);
945 }
946 return TRUE;
947}
948
949static gboolean
950handle_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, code: G_DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN,
956 format: "selinux context not supported");
957 _g_freedesktop_dbus_complete_get_connection_selinux_security_context (object, invocation, "");
958 return TRUE;
959}
960
961static gboolean
962handle_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, code: G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
968 format: "connection pid not supported");
969 return TRUE;
970}
971
972static gboolean
973handle_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, code: G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
979 format: "connection user not supported");
980 return TRUE;
981}
982
983static gboolean
984handle_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
993static gboolean
994handle_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 (s1: 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 (hash_table: daemon->clients, key: arg_name) == NULL)
1010 g_dbus_method_invocation_return_error (invocation,
1011 G_DBUS_ERROR, code: G_DBUS_ERROR_NAME_HAS_NO_OWNER,
1012 format: "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, str: arg_name);
1019 if (name == NULL || name->owner == NULL)
1020 {
1021 g_dbus_method_invocation_return_error (invocation,
1022 G_DBUS_ERROR, code: G_DBUS_ERROR_NAME_HAS_NO_OWNER,
1023 format: "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
1031static gboolean
1032handle_hello (_GFreedesktopDBus *object,
1033 GDBusMethodInvocation *invocation)
1034{
1035 Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), key: "client");
1036 _g_freedesktop_dbus_complete_hello (object, invocation, client->id);
1037
1038 g_dbus_connection_emit_signal (connection: client->connection,
1039 NULL, object_path: "/org/freedesktop/DBus",
1040 interface_name: "org.freedesktop.DBus", signal_name: "NameAcquired",
1041 parameters: g_variant_new (format_string: "(s)",
1042 client->id), NULL);
1043
1044 return TRUE;
1045}
1046
1047static gboolean
1048handle_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
1059static gboolean
1060handle_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 (hash_table: daemon->clients);
1070 for (l = clients; l != NULL; l = l->next)
1071 {
1072 Client *client = l->data;
1073
1074 g_ptr_array_add (array, data: client->id);
1075 }
1076
1077 g_list_free (list: clients);
1078
1079 names = g_hash_table_get_values (hash_table: daemon->names);
1080 for (l = names; l != NULL; l = l->next)
1081 {
1082 Name *name = l->data;
1083
1084 g_ptr_array_add (array, data: name->name);
1085 }
1086
1087 g_list_free (list: 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
1098static gboolean
1099handle_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, str: 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, data: 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
1130static gboolean
1131handle_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, str: arg_name);
1140 client = g_hash_table_lookup (hash_table: daemon->clients, key: arg_name);
1141
1142 _g_freedesktop_dbus_complete_name_has_owner (object, invocation,
1143 name != NULL || client != NULL);
1144 return TRUE;
1145}
1146
1147static gboolean
1148handle_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)), key: "client");
1153 GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1154 Name *name;
1155 guint32 result;
1156
1157 if (!g_dbus_is_name (string: arg_name))
1158 {
1159 g_dbus_method_invocation_return_error (invocation,
1160 G_DBUS_ERROR, code: G_DBUS_ERROR_INVALID_ARGS,
1161 format: "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, code: G_DBUS_ERROR_INVALID_ARGS,
1169 format: "Cannot release a service starting with ':' such as \"%s\"", arg_name);
1170 return TRUE;
1171 }
1172
1173 if (strcmp (s1: arg_name, DBUS_SERVICE_NAME) == 0)
1174 {
1175 g_dbus_method_invocation_return_error (invocation,
1176 G_DBUS_ERROR, code: G_DBUS_ERROR_INVALID_ARGS,
1177 format: "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, str: 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
1199static gboolean
1200handle_reload_config (_GFreedesktopDBus *object,
1201 GDBusMethodInvocation *invocation)
1202{
1203 _g_freedesktop_dbus_complete_reload_config (object, invocation);
1204 return TRUE;
1205}
1206
1207static gboolean
1208handle_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, code: G_DBUS_ERROR_FAILED,
1214 format: "UpdateActivationEnvironment not implemented");
1215 return TRUE;
1216}
1217
1218static gboolean
1219handle_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)), key: "client");
1224 Match *match, *other_match;
1225 GList *l;
1226
1227 match = match_new (str: arg_rule);
1228
1229 if (match == NULL)
1230 g_dbus_method_invocation_return_error (invocation,
1231 G_DBUS_ERROR, code: G_DBUS_ERROR_MATCH_RULE_INVALID,
1232 format: "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 (a: match, b: other_match))
1239 {
1240 match_free (match: other_match);
1241 client->matches = g_list_delete_link (list: client->matches, link_: l);
1242 break;
1243 }
1244 }
1245
1246 if (l == NULL)
1247 g_dbus_method_invocation_return_error (invocation,
1248 G_DBUS_ERROR, code: G_DBUS_ERROR_MATCH_RULE_NOT_FOUND,
1249 format: "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
1259static gboolean
1260handle_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)), key: "client");
1266 GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1267 Name *name;
1268 NameOwner *owner;
1269 guint32 result;
1270
1271 if (!g_dbus_is_name (string: arg_name))
1272 {
1273 g_dbus_method_invocation_return_error (invocation,
1274 G_DBUS_ERROR, code: G_DBUS_ERROR_INVALID_ARGS,
1275 format: "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, code: G_DBUS_ERROR_INVALID_ARGS,
1283 format: "Cannot acquire a service starting with ':' such as \"%s\"", arg_name);
1284 return TRUE;
1285 }
1286
1287 if (strcmp (s1: arg_name, DBUS_SERVICE_NAME) == 0)
1288 {
1289 g_dbus_method_invocation_return_error (invocation,
1290 G_DBUS_ERROR, code: G_DBUS_ERROR_INVALID_ARGS,
1291 format: "Cannot acquire a service named " DBUS_SERVICE_NAME ", because that is reserved");
1292 return TRUE;
1293 }
1294
1295 name = name_ensure (daemon, str: 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
1341static gboolean
1342handle_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, str: 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, code: G_DBUS_ERROR_SERVICE_UNKNOWN,
1357 format: "No support for activation for name: %s", arg_name);
1358
1359 return TRUE;
1360}
1361
1362G_GNUC_PRINTF(5, 6)
1363static void
1364return_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, args: var_args);
1378 va_end (var_args);
1379
1380 error = g_error_new_literal (domain, code, message: "");
1381 dbus_error_name = g_dbus_error_encode_gerror (error);
1382
1383 reply = g_dbus_message_new_method_error_literal (method_call_message: message,
1384 error_name: dbus_error_name,
1385 error_message);
1386
1387 g_error_free (error);
1388 g_free (mem: dbus_error_name);
1389 g_free (mem: error_message);
1390
1391 if (!g_dbus_connection_send_message (connection: client->connection, message: reply, flags: G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL))
1392 g_warning ("Error sending reply");
1393 g_object_unref (object: reply);
1394}
1395
1396static GDBusMessage *
1397route_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 (s1: dest, DBUS_SERVICE_NAME) != 0)
1408 {
1409 dest_client = g_hash_table_lookup (hash_table: daemon->clients, key: dest);
1410
1411 if (dest_client == NULL)
1412 {
1413 Name *name;
1414 name = name_lookup (daemon, str: 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 (client: source_client, message,
1423 G_DBUS_ERROR, code: G_DBUS_ERROR_SERVICE_UNKNOWN,
1424 format: "The name %s is unknown", dest);
1425 }
1426 else
1427 {
1428 GError *error = NULL;
1429
1430 if (!g_dbus_connection_send_message (connection: dest_client->connection, message, flags: G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL, NULL, error: &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, has_destination: dest_client != NULL, TRUE, not_to: dest_client);
1439
1440 /* Swallow messages not for the bus */
1441 if (dest == NULL || strcmp (s1: dest, DBUS_SERVICE_NAME) != 0)
1442 {
1443 g_object_unref (object: message);
1444 message = NULL;
1445 }
1446
1447 return message;
1448}
1449
1450static GDBusMessage *
1451copy_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 (object: message);
1457 message = copy;
1458 }
1459 return message;
1460}
1461
1462static GDBusMessage *
1463filter_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 (format: "%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, value: client->id);
1496
1497 return route_message (source_client: 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, value: client->id);
1516 }
1517
1518 return message;
1519}
1520
1521static gboolean
1522on_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 (tag: daemon->timeout);
1533 daemon->timeout = 0;
1534 }
1535
1536 client_new (daemon, connection);
1537
1538 return TRUE;
1539}
1540
1541static void
1542g_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 (tag: daemon->timeout);
1549
1550 clients = g_hash_table_get_values (hash_table: daemon->clients);
1551 for (l = clients; l != NULL; l = l->next)
1552 client_free (client: l->data);
1553 g_list_free (list: 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 (hash_table: daemon->clients);
1559 g_hash_table_destroy (hash_table: daemon->names);
1560
1561 g_object_unref (object: daemon->server);
1562
1563 if (daemon->tmpdir)
1564 {
1565 g_rmdir (filename: daemon->tmpdir);
1566 g_free (mem: daemon->tmpdir);
1567 }
1568
1569 g_free (mem: daemon->guid);
1570 g_free (mem: daemon->address);
1571
1572 G_OBJECT_CLASS (g_dbus_daemon_parent_class)->finalize (object);
1573}
1574
1575static void
1576g_dbus_daemon_init (GDBusDaemon *daemon)
1577{
1578 daemon->next_major_id = 1;
1579 daemon->clients = g_hash_table_new_full (hash_func: g_str_hash, key_equal_func: g_str_equal, NULL, NULL);
1580 daemon->names = g_hash_table_new_full (hash_func: g_str_hash, key_equal_func: g_str_equal, NULL, NULL);
1581 daemon->guid = g_dbus_generate_guid ();
1582}
1583
1584static gboolean
1585initable_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 (str: "unix:tmpdir=/tmp/gdbus-daemon");
1598 else
1599 {
1600 daemon->tmpdir = g_dir_make_tmp (tmpl: "gdbus-daemon-XXXXXX", NULL);
1601 daemon->address = g_strdup_printf (format: "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 (address: daemon->address,
1613 flags,
1614 guid: daemon->guid,
1615 NULL,
1616 cancellable,
1617 error);
1618 if (daemon->server == NULL)
1619 return FALSE;
1620
1621
1622 g_dbus_server_start (server: 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
1631static void
1632g_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 (mem: 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
1651static void
1652g_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, v_string: daemon->address);
1663 break;
1664
1665 default:
1666 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1667 }
1668}
1669
1670static void
1671g_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 signal_flags: G_SIGNAL_RUN_LAST,
1684 class_offset: 0,
1685 NULL, NULL,
1686 NULL,
1687 G_TYPE_NONE, n_params: 0);
1688
1689 g_object_class_install_property (oclass: gobject_class,
1690 property_id: PROP_ADDRESS,
1691 pspec: g_param_spec_string (name: "address",
1692 nick: "Bus Address",
1693 blurb: "The address the bus should use",
1694 NULL,
1695 flags: G_PARAM_READWRITE |
1696 G_PARAM_CONSTRUCT_ONLY |
1697 G_PARAM_STATIC_STRINGS));
1698}
1699
1700static void
1701g_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
1722static void
1723initable_iface_init (GInitableIface *initable_iface)
1724{
1725 initable_iface->init = initable_init;
1726}
1727
1728GDBusDaemon *
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 first_property_name: "address", address,
1737 NULL);
1738}
1739
1740const char *
1741_g_dbus_daemon_get_address (GDBusDaemon *daemon)
1742{
1743 return g_dbus_server_get_client_address (server: daemon->server);
1744}
1745

source code of gtk/subprojects/glib/gio/gdbusdaemon.c