8 #include <gio/gunixsocketaddress.h>
9 #include "gdbusdaemon.h"
12 #include "gdbus-daemon-generated.h"
14 #define DBUS_SERVICE_NAME "org.freedesktop.DBus"
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 */
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 */
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 */
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 */
36 #define IDLE_TIMEOUT_MSEC 3000
40 _GFreedesktopDBusSkeleton parent_instance;
49 guint32 next_major_id;
50 guint32 next_minor_id;
53 struct _GDBusDaemonClass
55 _GFreedesktopDBusSkeletonClass parent_class;
69 static guint g_dbus_daemon_signals[NR_SIGNALS];
72 static void initable_iface_init (GInitableIface *initable_iface);
73 static void g_dbus_daemon_iface_init (_GFreedesktopDBusIface *iface);
75 #define g_dbus_daemon_get_type _g_dbus_daemon_get_type
76 G_DEFINE_TYPE_WITH_CODE (GDBusDaemon, g_dbus_daemon, _G_TYPE_FREEDESKTOP_DBUS_SKELETON,
77 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)
78 G_IMPLEMENT_INTERFACE (_G_TYPE_FREEDESKTOP_DBUS, g_dbus_daemon_iface_init))
83 GDBusConnection *connection;
104 MATCH_ELEMENT_SENDER,
105 MATCH_ELEMENT_INTERFACE,
106 MATCH_ELEMENT_MEMBER,
108 MATCH_ELEMENT_PATH_NAMESPACE,
109 MATCH_ELEMENT_DESTINATION,
110 MATCH_ELEMENT_ARG0NAMESPACE,
111 MATCH_ELEMENT_EAVESDROP,
113 MATCH_ELEMENT_ARGNPATH,
124 GDBusMessageType type;
126 MatchElement *elements;
129 static GDBusMessage *filter_function (GDBusConnection *connection,
130 GDBusMessage *message,
133 static void connection_closed (GDBusConnection *connection,
134 gboolean remote_peer_vanished,
139 name_owner_new (Client *client, guint32 flags)
143 owner = g_new0 (NameOwner, 1);
144 owner->client = client;
145 owner->flags = flags;
150 name_owner_free (NameOwner *owner)
156 name_new (GDBusDaemon *daemon, const char *str)
160 name = g_new0 (Name, 1);
162 name->daemon = daemon;
163 name->name = g_strdup (str);
165 g_hash_table_insert (daemon->names, name->name, name);
171 name_ref (Name *name)
173 g_assert (name->refcount > 0);
179 name_unref (Name *name)
181 g_assert (name->refcount > 0);
182 if (--name->refcount == 0)
184 g_hash_table_remove (name->daemon->names, name->name);
191 name_ensure (GDBusDaemon *daemon, const char *str)
195 name = g_hash_table_lookup (daemon->names, str);
198 return name_ref (name);
199 return name_new (daemon, str);
203 name_lookup (GDBusDaemon *daemon, const char *str)
205 return g_hash_table_lookup (daemon->names, str);
209 is_key (const char *key_start, const char *key_end, const char *value)
211 gsize len = strlen (value);
213 if (len != key_end - key_start)
216 return strncmp (key_start, value, len) == 0;
220 parse_key (MatchElement *element, const char *key_start, const char *key_end)
224 if (is_key (key_start, key_end, "type"))
226 element->type = MATCH_ELEMENT_TYPE;
228 else if (is_key (key_start, key_end, "sender"))
230 element->type = MATCH_ELEMENT_SENDER;
232 else if (is_key (key_start, key_end, "interface"))
234 element->type = MATCH_ELEMENT_INTERFACE;
236 else if (is_key (key_start, key_end, "member"))
238 element->type = MATCH_ELEMENT_MEMBER;
240 else if (is_key (key_start, key_end, "path"))
242 element->type = MATCH_ELEMENT_PATH;
244 else if (is_key (key_start, key_end, "path_namespace"))
246 element->type = MATCH_ELEMENT_PATH_NAMESPACE;
248 else if (is_key (key_start, key_end, "destination"))
250 element->type = MATCH_ELEMENT_DESTINATION;
252 else if (is_key (key_start, key_end, "arg0namespace"))
254 element->type = MATCH_ELEMENT_ARG0NAMESPACE;
256 else if (is_key (key_start, key_end, "eavesdrop"))
258 element->type = MATCH_ELEMENT_EAVESDROP;
260 else if (key_end - key_start > 3 && is_key (key_start, key_start + 3, "arg"))
262 const char *digits = key_start + 3;
263 const char *end_digits = digits;
265 while (end_digits < key_end && g_ascii_isdigit (*end_digits))
268 if (end_digits == key_end) /* argN */
270 element->type = MATCH_ELEMENT_ARGN;
271 element->arg = atoi (digits);
273 else if (is_key (end_digits, key_end, "path")) /* argNpath */
275 element->type = MATCH_ELEMENT_ARGNPATH;
276 element->arg = atoi (digits);
288 parse_value (MatchElement *element, const char *s)
293 value = g_string_new ("");
316 g_string_append_c (value, *s);
320 else if (quote_char == '\\')
322 /* \ only counts as an escape if escaping a quote mark */
324 g_string_append_c (value, '\\');
326 g_string_append_c (value, *s);
329 else /* quote_char == ' */
334 g_string_append_c (value, *s);
340 if (quote_char == '\\')
341 g_string_append_c (value, '\\');
342 else if (quote_char == '\'')
344 g_string_free (value, TRUE);
348 element->value = g_string_free (value, FALSE);
353 match_new (const char *str)
358 const char *key_start;
360 MatchElement element;
362 GDBusMessageType type;
366 type = G_DBUS_MESSAGE_TYPE_INVALID;
367 elements = g_array_new (TRUE, TRUE, sizeof (MatchElement));
373 memset (&element, 0, sizeof (element));
375 /* Skip initial whitespace */
376 while (*p && g_ascii_isspace (*p))
381 /* Read non-whitespace non-equals chars */
382 while (*p && *p != '=' && !g_ascii_isspace (*p))
387 /* Skip any whitespace after key */
388 while (*p && g_ascii_isspace (*p))
391 if (key_start == key_end)
392 continue; /* Allow trailing whitespace */
399 if (!parse_key (&element, key_start, key_end))
402 p = parse_value (&element, p);
406 if (element.type == MATCH_ELEMENT_EAVESDROP)
408 if (strcmp (element.value, "true") == 0)
410 else if (strcmp (element.value, "false") == 0)
414 g_free (element.value);
417 g_free (element.value);
419 else if (element.type == MATCH_ELEMENT_TYPE)
421 if (strcmp (element.value, "signal") == 0)
422 type = G_DBUS_MESSAGE_TYPE_SIGNAL;
423 else if (strcmp (element.value, "method_call") == 0)
424 type = G_DBUS_MESSAGE_TYPE_METHOD_CALL;
425 else if (strcmp (element.value, "method_return") == 0)
426 type = G_DBUS_MESSAGE_TYPE_METHOD_RETURN;
427 else if (strcmp (element.value, "error") == 0)
428 type = G_DBUS_MESSAGE_TYPE_ERROR;
431 g_free (element.value);
434 g_free (element.value);
437 g_array_append_val (elements, element);
440 match = g_new0 (Match, 1);
441 match->n_elements = elements->len;
442 match->elements = (MatchElement *)g_array_free (elements, FALSE);
443 match->eavesdrop = eavesdrop;
449 for (i = 0; i < elements->len; i++)
450 g_free (g_array_index (elements, MatchElement, i).value);
451 g_array_free (elements, TRUE);
456 match_free (Match *match)
459 for (i = 0; i < match->n_elements; i++)
460 g_free (match->elements[i].value);
461 g_free (match->elements);
466 match_equal (Match *a, Match *b)
470 if (a->eavesdrop != b->eavesdrop)
472 if (a->type != b->type)
474 if (a->n_elements != b->n_elements)
476 for (i = 0; i < a->n_elements; i++)
478 if (a->elements[i].type != b->elements[i].type ||
479 a->elements[i].arg != b->elements[i].arg ||
480 strcmp (a->elements[i].value, b->elements[i].value) != 0)
487 message_get_argN (GDBusMessage *message, int n, gboolean allow_path)
494 body = g_dbus_message_get_body (message);
496 if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE_TUPLE))
499 item = g_variant_get_child_value (body, n);
500 if (g_variant_is_of_type (item, G_VARIANT_TYPE_STRING) ||
501 (allow_path && g_variant_is_of_type (item, G_VARIANT_TYPE_OBJECT_PATH)))
502 ret = g_variant_get_string (item, NULL);
503 g_variant_unref (item);
512 CHECK_TYPE_PATH_PREFIX,
513 CHECK_TYPE_PATH_RELATED,
514 CHECK_TYPE_NAMESPACE_PREFIX
518 match_matches (GDBusDaemon *daemon,
519 Match *match, GDBusMessage *message,
520 gboolean has_destination)
522 MatchElement *element;
528 if (has_destination && !match->eavesdrop)
531 if (match->type != G_DBUS_MESSAGE_TYPE_INVALID &&
532 g_dbus_message_get_message_type (message) != match->type)
535 for (i = 0; i < match->n_elements; i++)
537 element = &match->elements[i];
538 check_type = CHECK_TYPE_STRING;
539 switch (element->type)
541 case MATCH_ELEMENT_SENDER:
542 check_type = CHECK_TYPE_NAME;
543 value = g_dbus_message_get_sender (message);
545 value = DBUS_SERVICE_NAME;
547 case MATCH_ELEMENT_DESTINATION:
548 check_type = CHECK_TYPE_NAME;
549 value = g_dbus_message_get_destination (message);
551 case MATCH_ELEMENT_INTERFACE:
552 value = g_dbus_message_get_interface (message);
554 case MATCH_ELEMENT_MEMBER:
555 value = g_dbus_message_get_member (message);
557 case MATCH_ELEMENT_PATH:
558 value = g_dbus_message_get_path (message);
560 case MATCH_ELEMENT_PATH_NAMESPACE:
561 check_type = CHECK_TYPE_PATH_PREFIX;
562 value = g_dbus_message_get_path (message);
564 case MATCH_ELEMENT_ARG0NAMESPACE:
565 check_type = CHECK_TYPE_NAMESPACE_PREFIX;
566 value = message_get_argN (message, 0, FALSE);
568 case MATCH_ELEMENT_ARGN:
569 value = message_get_argN (message, element->arg, FALSE);
571 case MATCH_ELEMENT_ARGNPATH:
572 check_type = CHECK_TYPE_PATH_RELATED;
573 value = message_get_argN (message, element->arg, TRUE);
576 case MATCH_ELEMENT_TYPE:
577 case MATCH_ELEMENT_EAVESDROP:
578 g_assert_not_reached ();
586 case CHECK_TYPE_STRING:
587 if (strcmp (element->value, value) != 0)
590 case CHECK_TYPE_NAME:
591 name = name_lookup (daemon, element->value);
592 if (name != NULL && name->owner != NULL)
594 if (strcmp (name->owner->client->id, value) != 0)
597 else if (strcmp (element->value, value) != 0)
600 case CHECK_TYPE_PATH_PREFIX:
601 len = strlen (element->value);
603 /* Make sure to handle the case of element->value == '/'. */
607 /* Fail if there's no prefix match, or if the prefix match doesn't
608 * finish at the end of or at a separator in the @value. */
609 if (!g_str_has_prefix (value, element->value))
611 if (value[len] != 0 && value[len] != '/')
615 case CHECK_TYPE_PATH_RELATED:
616 len = strlen (element->value);
617 len2 = strlen (value);
619 if (!(strcmp (value, element->value) == 0 ||
620 (len2 > 0 && value[len2-1] == '/' && g_str_has_prefix (element->value, value)) ||
621 (len > 0 && element->value[len-1] == '/' && g_str_has_prefix (value, element->value))))
624 case CHECK_TYPE_NAMESPACE_PREFIX:
625 len = strlen (element->value);
626 if (!(g_str_has_prefix (value, element->value) &&
627 (value[len] == 0 || value[len] == '.')))
631 g_assert_not_reached ();
639 broadcast_message (GDBusDaemon *daemon,
640 GDBusMessage *message,
641 gboolean has_destination,
642 gboolean preserve_serial,
645 GList *clients, *l, *ll;
648 clients = g_hash_table_get_values (daemon->clients);
649 for (l = clients; l != NULL; l = l->next)
651 Client *client = l->data;
653 if (client == not_to)
656 for (ll = client->matches; ll != NULL; ll = ll->next)
658 Match *match = ll->data;
660 if (match_matches (daemon, match, message, has_destination))
666 copy = g_dbus_message_copy (message, NULL);
669 g_dbus_connection_send_message (client->connection, copy,
670 preserve_serial?G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL:0, NULL, NULL);
671 g_object_unref (copy);
676 g_list_free (clients);
680 send_name_owner_changed (GDBusDaemon *daemon,
682 const char *old_owner,
683 const char *new_owner)
685 GDBusMessage *signal_message;
687 signal_message = g_dbus_message_new_signal ("/org/freedesktop/DBus",
688 "org.freedesktop.DBus",
690 g_dbus_message_set_body (signal_message,
691 g_variant_new ("(sss)",
693 old_owner ? old_owner : "",
694 new_owner ? new_owner : ""));
696 broadcast_message (daemon, signal_message, FALSE, FALSE, NULL);
697 g_object_unref (signal_message);
702 name_unqueue_owner (Name *name, Client *client)
706 for (l = name->queue; l != NULL; l = l->next)
708 NameOwner *other = l->data;
710 if (other->client == client)
712 name->queue = g_list_delete_link (name->queue, l);
714 name_owner_free (other);
723 name_replace_owner (Name *name, NameOwner *owner)
725 GDBusDaemon *daemon = name->daemon;
726 NameOwner *old_owner;
727 char *old_name = NULL, *new_name = NULL;
728 Client *new_client = NULL;
731 new_client = owner->client;
735 old_owner = name->owner;
738 Client *old_client = old_owner->client;
740 g_assert (old_owner->client != new_client);
742 g_dbus_connection_emit_signal (old_client->connection,
743 NULL, "/org/freedesktop/DBus",
744 "org.freedesktop.DBus", "NameLost",
745 g_variant_new ("(s)",
748 old_name = g_strdup (old_client->id);
749 if (old_owner->flags & DBUS_NAME_FLAG_DO_NOT_QUEUE)
752 name_owner_free (old_owner);
755 name->queue = g_list_prepend (name->queue, old_owner);
761 name_unqueue_owner (name, owner->client);
763 new_name = new_client->id;
765 g_dbus_connection_emit_signal (new_client->connection,
766 NULL, "/org/freedesktop/DBus",
767 "org.freedesktop.DBus", "NameAcquired",
768 g_variant_new ("(s)",
772 send_name_owner_changed (daemon, name->name, old_name, new_name);
780 name_release_owner (Name *name)
782 NameOwner *next_owner = NULL;
786 /* Will someone else take over? */
789 next_owner = name->queue->data;
791 name->queue = g_list_delete_link (name->queue, name->queue);
794 name->owner->flags |= DBUS_NAME_FLAG_DO_NOT_QUEUE;
795 name_replace_owner (name, next_owner);
801 name_queue_owner (Name *name, NameOwner *owner)
805 for (l = name->queue; l != NULL; l = l->next)
807 NameOwner *other = l->data;
809 if (other->client == owner->client)
811 other->flags = owner->flags;
812 name_owner_free (owner);
817 name->queue = g_list_append (name->queue, owner);
822 client_new (GDBusDaemon *daemon, GDBusConnection *connection)
825 GError *error = NULL;
827 client = g_new0 (Client, 1);
828 client->daemon = daemon;
829 client->id = g_strdup_printf (":%d.%d", daemon->next_major_id, daemon->next_minor_id);
830 client->connection = g_object_ref (connection);
832 if (daemon->next_minor_id == G_MAXUINT32)
834 daemon->next_minor_id = 0;
835 daemon->next_major_id++;
838 daemon->next_minor_id++;
840 g_object_set_data (G_OBJECT (connection), "client", client);
841 g_hash_table_insert (daemon->clients, client->id, client);
843 g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (daemon), connection,
844 "/org/freedesktop/DBus", &error);
845 g_assert_no_error (error);
847 g_signal_connect (connection, "closed", G_CALLBACK (connection_closed), client);
848 g_dbus_connection_add_filter (connection,
852 send_name_owner_changed (daemon, client->id, NULL, client->id);
858 client_free (Client *client)
860 GDBusDaemon *daemon = client->daemon;
863 g_dbus_interface_skeleton_unexport_from_connection (G_DBUS_INTERFACE_SKELETON (daemon),
866 g_hash_table_remove (daemon->clients, client->id);
868 names = g_hash_table_get_values (daemon->names);
869 for (l = names; l != NULL; l = l->next)
871 Name *name = l->data;
875 if (name->owner && name->owner->client == client)
876 name_release_owner (name);
878 name_unqueue_owner (name, client);
884 send_name_owner_changed (daemon, client->id, client->id, NULL);
886 g_object_unref (client->connection);
888 for (l = client->matches; l != NULL; l = l->next)
889 match_free (l->data);
890 g_list_free (client->matches);
897 idle_timeout_cb (gpointer user_data)
899 GDBusDaemon *daemon = user_data;
903 g_signal_emit (daemon,
904 g_dbus_daemon_signals[SIGNAL_IDLE_TIMEOUT],
907 return G_SOURCE_REMOVE;
911 connection_closed (GDBusConnection *connection,
912 gboolean remote_peer_vanished,
916 GDBusDaemon *daemon = client->daemon;
918 client_free (client);
920 if (g_hash_table_size (daemon->clients) == 0)
921 daemon->timeout = g_timeout_add (IDLE_TIMEOUT_MSEC,
927 handle_add_match (_GFreedesktopDBus *object,
928 GDBusMethodInvocation *invocation,
929 const gchar *arg_rule)
931 Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
934 match = match_new (arg_rule);
937 g_dbus_method_invocation_return_error (invocation,
938 G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_INVALID,
939 "Invalid rule: %s", arg_rule);
942 client->matches = g_list_prepend (client->matches, match);
943 _g_freedesktop_dbus_complete_add_match (object, invocation);
949 handle_get_connection_selinux_security_context (_GFreedesktopDBus *object,
950 GDBusMethodInvocation *invocation,
951 const gchar *arg_name)
953 g_dbus_method_invocation_return_error (invocation,
954 G_DBUS_ERROR, G_DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN,
955 "selinux context not supported");
956 _g_freedesktop_dbus_complete_get_connection_selinux_security_context (object, invocation, "");
961 handle_get_connection_unix_process_id (_GFreedesktopDBus *object,
962 GDBusMethodInvocation *invocation,
963 const gchar *arg_name)
965 g_dbus_method_invocation_return_error (invocation,
966 G_DBUS_ERROR, G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
967 "connection pid not supported");
972 handle_get_connection_unix_user (_GFreedesktopDBus *object,
973 GDBusMethodInvocation *invocation,
974 const gchar *arg_name)
976 g_dbus_method_invocation_return_error (invocation,
977 G_DBUS_ERROR, G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
978 "connection user not supported");
983 handle_get_id (_GFreedesktopDBus *object,
984 GDBusMethodInvocation *invocation)
986 GDBusDaemon *daemon = G_DBUS_DAEMON (object);
987 _g_freedesktop_dbus_complete_get_id (object, invocation,
993 handle_get_name_owner (_GFreedesktopDBus *object,
994 GDBusMethodInvocation *invocation,
995 const gchar *arg_name)
997 GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1000 if (strcmp (arg_name, DBUS_SERVICE_NAME) == 0)
1002 _g_freedesktop_dbus_complete_get_name_owner (object, invocation, DBUS_SERVICE_NAME);
1006 if (arg_name[0] == ':')
1008 if (g_hash_table_lookup (daemon->clients, arg_name) == NULL)
1009 g_dbus_method_invocation_return_error (invocation,
1010 G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER,
1011 "Could not get owner of name '%s': no such name", arg_name);
1013 _g_freedesktop_dbus_complete_get_name_owner (object, invocation, arg_name);
1017 name = name_lookup (daemon, arg_name);
1018 if (name == NULL || name->owner == NULL)
1020 g_dbus_method_invocation_return_error (invocation,
1021 G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER,
1022 "Could not get owner of name '%s': no such name", arg_name);
1026 _g_freedesktop_dbus_complete_get_name_owner (object, invocation, name->owner->client->id);
1031 handle_hello (_GFreedesktopDBus *object,
1032 GDBusMethodInvocation *invocation)
1034 Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
1035 _g_freedesktop_dbus_complete_hello (object, invocation, client->id);
1037 g_dbus_connection_emit_signal (client->connection,
1038 NULL, "/org/freedesktop/DBus",
1039 "org.freedesktop.DBus", "NameAcquired",
1040 g_variant_new ("(s)",
1047 handle_list_activatable_names (_GFreedesktopDBus *object,
1048 GDBusMethodInvocation *invocation)
1050 const char *names[] = { NULL };
1052 _g_freedesktop_dbus_complete_list_activatable_names (object,
1059 handle_list_names (_GFreedesktopDBus *object,
1060 GDBusMethodInvocation *invocation)
1062 GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1064 GList *clients, *names, *l;
1066 array = g_ptr_array_new ();
1068 clients = g_hash_table_get_values (daemon->clients);
1069 for (l = clients; l != NULL; l = l->next)
1071 Client *client = l->data;
1073 g_ptr_array_add (array, client->id);
1076 g_list_free (clients);
1078 names = g_hash_table_get_values (daemon->names);
1079 for (l = names; l != NULL; l = l->next)
1081 Name *name = l->data;
1083 g_ptr_array_add (array, name->name);
1086 g_list_free (names);
1088 g_ptr_array_add (array, NULL);
1090 _g_freedesktop_dbus_complete_list_names (object,
1092 (const gchar * const*)array->pdata);
1093 g_ptr_array_free (array, TRUE);
1098 handle_list_queued_owners (_GFreedesktopDBus *object,
1099 GDBusMethodInvocation *invocation,
1100 const gchar *arg_name)
1102 GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1107 array = g_ptr_array_new ();
1109 name = name_lookup (daemon, arg_name);
1110 if (name && name->owner)
1112 for (l = name->queue; l != NULL; l = l->next)
1114 Client *client = l->data;
1116 g_ptr_array_add (array, client->id);
1120 g_ptr_array_add (array, NULL);
1122 _g_freedesktop_dbus_complete_list_queued_owners (object,
1124 (const gchar * const*)array->pdata);
1125 g_ptr_array_free (array, TRUE);
1130 handle_name_has_owner (_GFreedesktopDBus *object,
1131 GDBusMethodInvocation *invocation,
1132 const gchar *arg_name)
1134 GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1138 name = name_lookup (daemon, arg_name);
1139 client = g_hash_table_lookup (daemon->clients, arg_name);
1141 _g_freedesktop_dbus_complete_name_has_owner (object, invocation,
1142 name != NULL || client != NULL);
1147 handle_release_name (_GFreedesktopDBus *object,
1148 GDBusMethodInvocation *invocation,
1149 const gchar *arg_name)
1151 Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
1152 GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1156 if (!g_dbus_is_name (arg_name))
1158 g_dbus_method_invocation_return_error (invocation,
1159 G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
1160 "Given bus name \"%s\" is not valid", arg_name);
1164 if (*arg_name == ':')
1166 g_dbus_method_invocation_return_error (invocation,
1167 G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
1168 "Cannot release a service starting with ':' such as \"%s\"", arg_name);
1172 if (strcmp (arg_name, DBUS_SERVICE_NAME) == 0)
1174 g_dbus_method_invocation_return_error (invocation,
1175 G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
1176 "Cannot release a service named " DBUS_SERVICE_NAME ", because that is owned by the bus");
1180 name = name_lookup (daemon, arg_name);
1183 result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
1184 else if (name->owner && name->owner->client == client)
1186 name_release_owner (name);
1187 result = DBUS_RELEASE_NAME_REPLY_RELEASED;
1189 else if (name_unqueue_owner (name, client))
1190 result = DBUS_RELEASE_NAME_REPLY_RELEASED;
1192 result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
1194 _g_freedesktop_dbus_complete_release_name (object, invocation, result);
1199 handle_reload_config (_GFreedesktopDBus *object,
1200 GDBusMethodInvocation *invocation)
1202 _g_freedesktop_dbus_complete_reload_config (object, invocation);
1207 handle_update_activation_environment (_GFreedesktopDBus *object,
1208 GDBusMethodInvocation *invocation,
1209 GVariant *arg_environment)
1211 g_dbus_method_invocation_return_error (invocation,
1212 G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1213 "UpdateActivationEnvironment not implemented");
1218 handle_remove_match (_GFreedesktopDBus *object,
1219 GDBusMethodInvocation *invocation,
1220 const gchar *arg_rule)
1222 Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
1223 Match *match, *other_match;
1226 match = match_new (arg_rule);
1229 g_dbus_method_invocation_return_error (invocation,
1230 G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_INVALID,
1231 "Invalid rule: %s", arg_rule);
1234 for (l = client->matches; l != NULL; l = l->next)
1236 other_match = l->data;
1237 if (match_equal (match, other_match))
1239 match_free (other_match);
1240 client->matches = g_list_delete_link (client->matches, l);
1246 g_dbus_method_invocation_return_error (invocation,
1247 G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_NOT_FOUND,
1248 "The given match rule wasn't found and can't be removed");
1250 _g_freedesktop_dbus_complete_remove_match (object, invocation);
1259 handle_request_name (_GFreedesktopDBus *object,
1260 GDBusMethodInvocation *invocation,
1261 const gchar *arg_name,
1264 Client *client = g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation)), "client");
1265 GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1270 if (!g_dbus_is_name (arg_name))
1272 g_dbus_method_invocation_return_error (invocation,
1273 G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
1274 "Requested bus name \"%s\" is not valid", arg_name);
1278 if (*arg_name == ':')
1280 g_dbus_method_invocation_return_error (invocation,
1281 G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
1282 "Cannot acquire a service starting with ':' such as \"%s\"", arg_name);
1286 if (strcmp (arg_name, DBUS_SERVICE_NAME) == 0)
1288 g_dbus_method_invocation_return_error (invocation,
1289 G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
1290 "Cannot acquire a service named " DBUS_SERVICE_NAME ", because that is reserved");
1294 name = name_ensure (daemon, arg_name);
1295 if (name->owner == NULL)
1297 owner = name_owner_new (client, flags);
1298 name_replace_owner (name, owner);
1300 result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
1302 else if (name->owner && name->owner->client == client)
1304 name->owner->flags = flags;
1305 result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
1307 else if ((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
1308 (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) ||
1309 !(name->owner->flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT)))
1311 /* Unqueue if queued */
1312 name_unqueue_owner (name, client);
1313 result = DBUS_REQUEST_NAME_REPLY_EXISTS;
1315 else if (!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
1316 (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) ||
1317 !(name->owner->flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT)))
1319 /* Queue the connection */
1320 owner = name_owner_new (client, flags);
1321 name_queue_owner (name, owner);
1322 result = DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
1326 /* Replace the current owner */
1328 owner = name_owner_new (client, flags);
1329 name_replace_owner (name, owner);
1331 result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
1336 _g_freedesktop_dbus_complete_request_name (object, invocation, result);
1341 handle_start_service_by_name (_GFreedesktopDBus *object,
1342 GDBusMethodInvocation *invocation,
1343 const gchar *arg_name,
1346 GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1349 name = name_lookup (daemon, arg_name);
1351 _g_freedesktop_dbus_complete_start_service_by_name (object, invocation,
1352 DBUS_START_REPLY_ALREADY_RUNNING);
1354 g_dbus_method_invocation_return_error (invocation,
1355 G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN,
1356 "No support for activation for name: %s", arg_name);
1363 return_error (Client *client, GDBusMessage *message,
1366 const gchar *format,
1369 GDBusMessage *reply;
1371 char *error_message;
1373 gchar *dbus_error_name;
1375 va_start (var_args, format);
1376 error_message = g_strdup_vprintf (format, var_args);
1379 error = g_error_new_literal (domain, code, "");
1380 dbus_error_name = g_dbus_error_encode_gerror (error);
1382 reply = g_dbus_message_new_method_error_literal (message,
1386 g_error_free (error);
1387 g_free (dbus_error_name);
1388 g_free (error_message);
1390 if (!g_dbus_connection_send_message (client->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL))
1391 g_warning ("Error sending reply");
1392 g_object_unref (reply);
1395 static GDBusMessage *
1396 route_message (Client *source_client, GDBusMessage *message)
1399 Client *dest_client;
1400 GDBusDaemon *daemon;
1402 daemon = source_client->daemon;
1405 dest = g_dbus_message_get_destination (message);
1406 if (dest != NULL && strcmp (dest, DBUS_SERVICE_NAME) != 0)
1408 dest_client = g_hash_table_lookup (daemon->clients, dest);
1410 if (dest_client == NULL)
1413 name = name_lookup (daemon, dest);
1414 if (name && name->owner)
1415 dest_client = name->owner->client;
1418 if (dest_client == NULL)
1420 if (g_dbus_message_get_message_type (message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL)
1421 return_error (source_client, message,
1422 G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN,
1423 "The name %s is unknown", dest);
1427 GError *error = NULL;
1429 if (!g_dbus_connection_send_message (dest_client->connection, message, G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL, NULL, &error))
1431 g_warning ("Error forwarding message: %s", error->message);
1432 g_error_free (error);
1437 broadcast_message (daemon, message, dest_client != NULL, TRUE, dest_client);
1439 /* Swallow messages not for the bus */
1440 if (dest == NULL || strcmp (dest, DBUS_SERVICE_NAME) != 0)
1442 g_object_unref (message);
1449 static GDBusMessage *
1450 copy_if_locked (GDBusMessage *message)
1452 if (g_dbus_message_get_locked (message))
1454 GDBusMessage *copy = g_dbus_message_copy (message, NULL);
1455 g_object_unref (message);
1461 static GDBusMessage *
1462 filter_function (GDBusConnection *connection,
1463 GDBusMessage *message,
1467 Client *client = user_data;
1471 const char *types[] = {"invalid", "method_call", "method_return", "error", "signal" };
1472 g_printerr ("%s%s %s %d(%d) sender: %s destination: %s %s %s.%s\n",
1474 incoming? "->" : "<-",
1475 types[g_dbus_message_get_message_type (message)],
1476 g_dbus_message_get_serial (message),
1477 g_dbus_message_get_reply_serial (message),
1478 g_dbus_message_get_sender (message),
1479 g_dbus_message_get_destination (message),
1480 g_dbus_message_get_path (message),
1481 g_dbus_message_get_interface (message),
1482 g_dbus_message_get_member (message));
1487 /* Ensure its not locked so we can set the sender */
1488 message = copy_if_locked (message);
1489 if (message == NULL)
1491 g_warning ("Failed to copy incoming message");
1494 g_dbus_message_set_sender (message, client->id);
1496 return route_message (client, message);
1500 if (g_dbus_message_get_sender (message) == NULL ||
1501 g_dbus_message_get_destination (message) == NULL)
1503 message = copy_if_locked (message);
1504 if (message == NULL)
1506 g_warning ("Failed to copy outgoing message");
1511 if (g_dbus_message_get_sender (message) == NULL)
1512 g_dbus_message_set_sender (message, DBUS_SERVICE_NAME);
1513 if (g_dbus_message_get_destination (message) == NULL)
1514 g_dbus_message_set_destination (message, client->id);
1521 on_new_connection (GDBusServer *server,
1522 GDBusConnection *connection,
1525 GDBusDaemon *daemon = user_data;
1527 g_dbus_connection_set_exit_on_close (connection, FALSE);
1529 if (daemon->timeout)
1531 g_source_remove (daemon->timeout);
1532 daemon->timeout = 0;
1535 client_new (daemon, connection);
1541 on_authorize_authenticated_peer (GDBusAuthObserver *observer,
1543 GCredentials *credentials,
1546 gboolean authorized = FALSE;
1548 if (credentials != NULL)
1550 GCredentials *own_credentials;
1552 own_credentials = g_credentials_new ();
1553 authorized = g_credentials_is_same_user (credentials, own_credentials, NULL);
1554 g_object_unref (own_credentials);
1559 /* We allow ANONYMOUS authentication on Windows for now, in
1560 * combination with the nonce-tcp transport. */
1569 g_dbus_daemon_finalize (GObject *object)
1571 GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1574 if (daemon->timeout)
1575 g_source_remove (daemon->timeout);
1577 clients = g_hash_table_get_values (daemon->clients);
1578 for (l = clients; l != NULL; l = l->next)
1579 client_free (l->data);
1580 g_list_free (clients);
1582 g_assert (g_hash_table_size (daemon->clients) == 0);
1583 g_assert (g_hash_table_size (daemon->names) == 0);
1585 g_hash_table_destroy (daemon->clients);
1586 g_hash_table_destroy (daemon->names);
1588 g_object_unref (daemon->server);
1592 g_rmdir (daemon->tmpdir);
1593 g_free (daemon->tmpdir);
1596 g_free (daemon->guid);
1597 g_free (daemon->address);
1599 G_OBJECT_CLASS (g_dbus_daemon_parent_class)->finalize (object);
1603 g_dbus_daemon_init (GDBusDaemon *daemon)
1605 daemon->next_major_id = 1;
1606 daemon->clients = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
1607 daemon->names = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
1608 daemon->guid = g_dbus_generate_guid ();
1612 initable_init (GInitable *initable,
1613 GCancellable *cancellable,
1616 GDBusDaemon *daemon = G_DBUS_DAEMON (initable);
1617 GDBusAuthObserver *observer;
1618 GDBusServerFlags flags;
1620 flags = G_DBUS_SERVER_FLAGS_NONE;
1621 if (daemon->address == NULL)
1624 if (g_unix_socket_address_abstract_names_supported ())
1625 daemon->address = g_strdup ("unix:tmpdir=/tmp/gdbus-daemon");
1628 daemon->tmpdir = g_dir_make_tmp ("gdbus-daemon-XXXXXX", NULL);
1629 daemon->address = g_strdup_printf ("unix:tmpdir=%s", daemon->tmpdir);
1632 daemon->address = g_strdup ("nonce-tcp:");
1633 flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS;
1637 observer = g_dbus_auth_observer_new ();
1638 daemon->server = g_dbus_server_new_sync (daemon->address,
1644 if (daemon->server == NULL)
1646 g_object_unref (observer);
1651 g_dbus_server_start (daemon->server);
1653 g_signal_connect (daemon->server, "new-connection",
1654 G_CALLBACK (on_new_connection),
1656 g_signal_connect (observer,
1657 "authorize-authenticated-peer",
1658 G_CALLBACK (on_authorize_authenticated_peer),
1661 g_object_unref (observer);
1667 g_dbus_daemon_set_property (GObject *object,
1669 const GValue *value,
1672 GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1677 g_free (daemon->address);
1678 daemon->address = g_value_dup_string (value);
1682 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1687 g_dbus_daemon_get_property (GObject *object,
1692 GDBusDaemon *daemon = G_DBUS_DAEMON (object);
1697 g_value_set_string (value, daemon->address);
1701 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1706 g_dbus_daemon_class_init (GDBusDaemonClass *klass)
1708 GObjectClass *gobject_class;
1710 gobject_class = G_OBJECT_CLASS (klass);
1711 gobject_class->finalize = g_dbus_daemon_finalize;
1712 gobject_class->set_property = g_dbus_daemon_set_property;
1713 gobject_class->get_property = g_dbus_daemon_get_property;
1715 g_dbus_daemon_signals[SIGNAL_IDLE_TIMEOUT] =
1716 g_signal_new (I_("idle-timeout"),
1724 g_object_class_install_property (gobject_class,
1726 g_param_spec_string ("address",
1728 "The address the bus should use",
1731 G_PARAM_CONSTRUCT_ONLY |
1732 G_PARAM_STATIC_STRINGS));
1736 g_dbus_daemon_iface_init (_GFreedesktopDBusIface *iface)
1738 iface->handle_add_match = handle_add_match;
1739 iface->handle_get_connection_selinux_security_context = handle_get_connection_selinux_security_context;
1740 iface->handle_get_connection_unix_process_id = handle_get_connection_unix_process_id;
1741 iface->handle_get_connection_unix_user = handle_get_connection_unix_user;
1742 iface->handle_get_id = handle_get_id;
1743 iface->handle_get_name_owner = handle_get_name_owner;
1744 iface->handle_hello = handle_hello;
1745 iface->handle_list_activatable_names = handle_list_activatable_names;
1746 iface->handle_list_names = handle_list_names;
1747 iface->handle_list_queued_owners = handle_list_queued_owners;
1748 iface->handle_name_has_owner = handle_name_has_owner;
1749 iface->handle_release_name = handle_release_name;
1750 iface->handle_reload_config = handle_reload_config;
1751 iface->handle_update_activation_environment = handle_update_activation_environment;
1752 iface->handle_remove_match = handle_remove_match;
1753 iface->handle_request_name = handle_request_name;
1754 iface->handle_start_service_by_name = handle_start_service_by_name;
1758 initable_iface_init (GInitableIface *initable_iface)
1760 initable_iface->init = initable_init;
1764 _g_dbus_daemon_new (const char *address,
1765 GCancellable *cancellable,
1768 return g_initable_new (G_TYPE_DBUS_DAEMON,
1776 _g_dbus_daemon_get_address (GDBusDaemon *daemon)
1778 return g_dbus_server_get_client_address (daemon->server);