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
)
178 name_unref (Name
*name
)
180 if (--name
->refcount
== 0)
182 g_hash_table_remove (name
->daemon
->names
, name
->name
);
189 name_ensure (GDBusDaemon
*daemon
, const char *str
)
193 name
= g_hash_table_lookup (daemon
->names
, str
);
196 return name_ref (name
);
197 return name_new (daemon
, str
);
201 name_lookup (GDBusDaemon
*daemon
, const char *str
)
203 return g_hash_table_lookup (daemon
->names
, str
);
207 is_key (const char *key_start
, const char *key_end
, char *value
)
209 gsize len
= strlen (value
);
211 if (len
!= key_end
- key_start
)
214 return strncmp (key_start
, value
, len
) == 0;
218 parse_key (MatchElement
*element
, const char *key_start
, const char *key_end
)
222 if (is_key (key_start
, key_end
, "type"))
224 element
->type
= MATCH_ELEMENT_TYPE
;
226 else if (is_key (key_start
, key_end
, "sender"))
228 element
->type
= MATCH_ELEMENT_SENDER
;
230 else if (is_key (key_start
, key_end
, "interface"))
232 element
->type
= MATCH_ELEMENT_INTERFACE
;
234 else if (is_key (key_start
, key_end
, "member"))
236 element
->type
= MATCH_ELEMENT_MEMBER
;
238 else if (is_key (key_start
, key_end
, "path"))
240 element
->type
= MATCH_ELEMENT_PATH
;
242 else if (is_key (key_start
, key_end
, "path_namespace"))
244 element
->type
= MATCH_ELEMENT_PATH_NAMESPACE
;
246 else if (is_key (key_start
, key_end
, "destination"))
248 element
->type
= MATCH_ELEMENT_DESTINATION
;
250 else if (is_key (key_start
, key_end
, "arg0namespace"))
252 element
->type
= MATCH_ELEMENT_ARG0NAMESPACE
;
254 else if (is_key (key_start
, key_end
, "eavesdrop"))
256 element
->type
= MATCH_ELEMENT_EAVESDROP
;
258 else if (key_end
- key_start
> 3 && is_key (key_start
, key_start
+ 3, "arg"))
260 const char *digits
= key_start
+ 3;
261 const char *end_digits
= digits
;
263 while (end_digits
< key_end
&& g_ascii_isdigit (*end_digits
))
266 if (end_digits
== key_end
) /* argN */
268 element
->type
= MATCH_ELEMENT_ARGN
;
269 element
->arg
= atoi (digits
);
271 else if (is_key (end_digits
, key_end
, "path")) /* argNpath */
273 element
->type
= MATCH_ELEMENT_ARGNPATH
;
274 element
->arg
= atoi (digits
);
286 parse_value (MatchElement
*element
, const char *s
)
291 value
= g_string_new ("");
314 g_string_append_c (value
, *s
);
318 else if (quote_char
== '\\')
320 /* \ only counts as an escape if escaping a quote mark */
322 g_string_append_c (value
, '\\');
324 g_string_append_c (value
, *s
);
327 else /* quote_char == ' */
332 g_string_append_c (value
, *s
);
338 if (quote_char
== '\\')
339 g_string_append_c (value
, '\\');
340 else if (quote_char
== '\'')
342 g_string_free (value
, TRUE
);
346 element
->value
= g_string_free (value
, FALSE
);
351 match_new (const char *str
)
356 const char *key_start
;
358 MatchElement element
;
360 GDBusMessageType type
;
364 type
= G_DBUS_MESSAGE_TYPE_INVALID
;
365 elements
= g_array_new (TRUE
, TRUE
, sizeof (MatchElement
));
371 memset (&element
, 0, sizeof (element
));
373 /* Skip initial whitespace */
374 while (*p
&& g_ascii_isspace (*p
))
379 /* Read non-whitespace non-equals chars */
380 while (*p
&& *p
!= '=' && !g_ascii_isspace (*p
))
385 /* Skip any whitespace after key */
386 while (*p
&& g_ascii_isspace (*p
))
389 if (key_start
== key_end
)
390 continue; /* Allow trailing whitespace */
397 if (!parse_key (&element
, key_start
, key_end
))
400 p
= parse_value (&element
, p
);
404 if (element
.type
== MATCH_ELEMENT_EAVESDROP
)
406 if (strcmp (element
.value
, "true") == 0)
408 else if (strcmp (element
.value
, "false") == 0)
412 g_free (element
.value
);
415 g_free (element
.value
);
417 else if (element
.type
== MATCH_ELEMENT_TYPE
)
419 if (strcmp (element
.value
, "signal") == 0)
420 type
= G_DBUS_MESSAGE_TYPE_SIGNAL
;
421 else if (strcmp (element
.value
, "method_call") == 0)
422 type
= G_DBUS_MESSAGE_TYPE_METHOD_CALL
;
423 else if (strcmp (element
.value
, "method_return") == 0)
424 type
= G_DBUS_MESSAGE_TYPE_METHOD_RETURN
;
425 else if (strcmp (element
.value
, "error") == 0)
426 type
= G_DBUS_MESSAGE_TYPE_ERROR
;
429 g_free (element
.value
);
432 g_free (element
.value
);
435 g_array_append_val (elements
, element
);
438 match
= g_new0 (Match
, 1);
439 match
->n_elements
= elements
->len
;
440 match
->elements
= (MatchElement
*)g_array_free (elements
, FALSE
);
441 match
->eavesdrop
= eavesdrop
;
447 for (i
= 0; i
< elements
->len
; i
++)
448 g_free (g_array_index (elements
, MatchElement
, i
).value
);
449 g_array_free (elements
, TRUE
);
454 match_free (Match
*match
)
457 for (i
= 0; i
< match
->n_elements
; i
++)
458 g_free (match
->elements
[i
].value
);
459 g_free (match
->elements
);
464 match_equal (Match
*a
, Match
*b
)
468 if (a
->eavesdrop
!= b
->eavesdrop
)
470 if (a
->type
!= b
->type
)
472 if (a
->n_elements
!= b
->n_elements
)
474 for (i
= 0; i
< a
->n_elements
; i
++)
476 if (a
->elements
[i
].type
!= b
->elements
[i
].type
||
477 a
->elements
[i
].arg
!= b
->elements
[i
].arg
||
478 strcmp (a
->elements
[i
].value
, b
->elements
[i
].value
) != 0)
485 message_get_argN (GDBusMessage
*message
, int n
, gboolean allow_path
)
492 body
= g_dbus_message_get_body (message
);
494 if (body
!= NULL
&& g_variant_is_of_type (body
, G_VARIANT_TYPE_TUPLE
))
497 item
= g_variant_get_child_value (body
, n
);
498 if (g_variant_is_of_type (item
, G_VARIANT_TYPE_STRING
) ||
499 (allow_path
&& g_variant_is_of_type (item
, G_VARIANT_TYPE_OBJECT_PATH
)))
500 ret
= g_variant_get_string (item
, NULL
);
501 g_variant_unref (item
);
510 CHECK_TYPE_PATH_PREFIX
,
511 CHECK_TYPE_PATH_RELATED
,
512 CHECK_TYPE_NAMESPACE_PREFIX
516 match_matches (GDBusDaemon
*daemon
,
517 Match
*match
, GDBusMessage
*message
,
518 gboolean has_destination
)
520 MatchElement
*element
;
526 if (has_destination
&& !match
->eavesdrop
)
529 if (match
->type
!= G_DBUS_MESSAGE_TYPE_INVALID
&&
530 g_dbus_message_get_message_type (message
) != match
->type
)
533 for (i
= 0; i
< match
->n_elements
; i
++)
535 element
= &match
->elements
[i
];
536 check_type
= CHECK_TYPE_STRING
;
537 switch (element
->type
)
539 case MATCH_ELEMENT_SENDER
:
540 check_type
= CHECK_TYPE_NAME
;
541 value
= g_dbus_message_get_sender (message
);
543 value
= DBUS_SERVICE_NAME
;
545 case MATCH_ELEMENT_DESTINATION
:
546 check_type
= CHECK_TYPE_NAME
;
547 value
= g_dbus_message_get_destination (message
);
549 case MATCH_ELEMENT_INTERFACE
:
550 value
= g_dbus_message_get_interface (message
);
552 case MATCH_ELEMENT_MEMBER
:
553 value
= g_dbus_message_get_member (message
);
555 case MATCH_ELEMENT_PATH
:
556 value
= g_dbus_message_get_path (message
);
558 case MATCH_ELEMENT_PATH_NAMESPACE
:
559 check_type
= CHECK_TYPE_PATH_PREFIX
;
560 value
= g_dbus_message_get_path (message
);
562 case MATCH_ELEMENT_ARG0NAMESPACE
:
563 check_type
= CHECK_TYPE_NAMESPACE_PREFIX
;
564 value
= message_get_argN (message
, 0, FALSE
);
566 case MATCH_ELEMENT_ARGN
:
567 value
= message_get_argN (message
, element
->arg
, FALSE
);
569 case MATCH_ELEMENT_ARGNPATH
:
570 check_type
= CHECK_TYPE_PATH_RELATED
;
571 value
= message_get_argN (message
, element
->arg
, TRUE
);
574 case MATCH_ELEMENT_TYPE
:
575 case MATCH_ELEMENT_EAVESDROP
:
576 g_assert_not_reached ();
584 case CHECK_TYPE_STRING
:
585 if (strcmp (element
->value
, value
) != 0)
588 case CHECK_TYPE_NAME
:
589 name
= name_lookup (daemon
, element
->value
);
590 if (name
!= NULL
&& name
->owner
!= NULL
)
592 if (strcmp (name
->owner
->client
->id
, value
) != 0)
595 else if (strcmp (element
->value
, value
) != 0)
598 case CHECK_TYPE_PATH_PREFIX
:
599 len
= strlen (element
->value
);
601 /* Make sure to handle the case of element->value == '/'. */
605 /* Fail if there's no prefix match, or if the prefix match doesn't
606 * finish at the end of or at a separator in the @value. */
607 if (!g_str_has_prefix (value
, element
->value
))
609 if (value
[len
] != 0 && value
[len
] != '/')
613 case CHECK_TYPE_PATH_RELATED
:
614 len
= strlen (element
->value
);
615 len2
= strlen (value
);
617 if (!(strcmp (value
, element
->value
) == 0 ||
618 (len2
> 0 && value
[len2
-1] == '/' && g_str_has_prefix (element
->value
, value
)) ||
619 (len
> 0 && element
->value
[len
-1] == '/' && g_str_has_prefix (value
, element
->value
))))
622 case CHECK_TYPE_NAMESPACE_PREFIX
:
623 len
= strlen (element
->value
);
624 if (!(g_str_has_prefix (value
, element
->value
) &&
625 (value
[len
] == 0 || value
[len
] == '.')))
629 g_assert_not_reached ();
637 broadcast_message (GDBusDaemon
*daemon
,
638 GDBusMessage
*message
,
639 gboolean has_destination
,
640 gboolean preserve_serial
,
643 GList
*clients
, *l
, *ll
;
646 clients
= g_hash_table_get_values (daemon
->clients
);
647 for (l
= clients
; l
!= NULL
; l
= l
->next
)
649 Client
*client
= l
->data
;
651 if (client
== not_to
)
654 for (ll
= client
->matches
; ll
!= NULL
; ll
= ll
->next
)
656 Match
*match
= ll
->data
;
658 if (match_matches (daemon
, match
, message
, has_destination
))
664 copy
= g_dbus_message_copy (message
, NULL
);
667 g_dbus_connection_send_message (client
->connection
, copy
,
668 preserve_serial
?G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL
:0, NULL
, NULL
);
669 g_object_unref (copy
);
674 g_list_free (clients
);
678 send_name_owner_changed (GDBusDaemon
*daemon
,
680 const char *old_owner
,
681 const char *new_owner
)
683 GDBusMessage
*signal_message
;
685 signal_message
= g_dbus_message_new_signal ("/org/freedesktop/DBus",
686 "org.freedesktop.DBus",
688 g_dbus_message_set_body (signal_message
,
689 g_variant_new ("(sss)",
691 old_owner
? old_owner
: "",
692 new_owner
? new_owner
: ""));
694 broadcast_message (daemon
, signal_message
, FALSE
, FALSE
, NULL
);
695 g_object_unref (signal_message
);
700 name_unqueue_owner (Name
*name
, Client
*client
)
704 for (l
= name
->queue
; l
!= NULL
; l
= l
->next
)
706 NameOwner
*other
= l
->data
;
708 if (other
->client
== client
)
710 name
->queue
= g_list_delete_link (name
->queue
, l
);
712 name_owner_free (other
);
721 name_replace_owner (Name
*name
, NameOwner
*owner
)
723 GDBusDaemon
*daemon
= name
->daemon
;
724 NameOwner
*old_owner
;
725 char *old_name
= NULL
, *new_name
= NULL
;
726 Client
*new_client
= NULL
;
729 new_client
= owner
->client
;
733 old_owner
= name
->owner
;
736 Client
*old_client
= old_owner
->client
;
738 g_assert (old_owner
->client
!= new_client
);
740 g_dbus_connection_emit_signal (old_client
->connection
,
741 NULL
, "/org/freedesktop/DBus",
742 "org.freedesktop.DBus", "NameLost",
743 g_variant_new ("(s)",
746 old_name
= g_strdup (old_client
->id
);
747 if (old_owner
->flags
& DBUS_NAME_FLAG_DO_NOT_QUEUE
)
750 name_owner_free (old_owner
);
753 name
->queue
= g_list_prepend (name
->queue
, old_owner
);
759 name_unqueue_owner (name
, owner
->client
);
761 new_name
= new_client
->id
;
763 g_dbus_connection_emit_signal (new_client
->connection
,
764 NULL
, "/org/freedesktop/DBus",
765 "org.freedesktop.DBus", "NameAcquired",
766 g_variant_new ("(s)",
770 send_name_owner_changed (daemon
, name
->name
, old_name
, new_name
);
778 name_release_owner (Name
*name
)
780 NameOwner
*next_owner
= NULL
;
784 /* Will someone else take over? */
787 next_owner
= name
->queue
->data
;
789 name
->queue
= g_list_delete_link (name
->queue
, name
->queue
);
792 name
->owner
->flags
|= DBUS_NAME_FLAG_DO_NOT_QUEUE
;
793 name_replace_owner (name
, next_owner
);
799 name_queue_owner (Name
*name
, NameOwner
*owner
)
803 for (l
= name
->queue
; l
!= NULL
; l
= l
->next
)
805 NameOwner
*other
= l
->data
;
807 if (other
->client
== owner
->client
)
809 other
->flags
= owner
->flags
;
810 name_owner_free (owner
);
815 name
->queue
= g_list_append (name
->queue
, owner
);
820 client_new (GDBusDaemon
*daemon
, GDBusConnection
*connection
)
823 GError
*error
= NULL
;
825 client
= g_new0 (Client
, 1);
826 client
->daemon
= daemon
;
827 client
->id
= g_strdup_printf (":%d.%d", daemon
->next_major_id
, daemon
->next_minor_id
);
828 client
->connection
= g_object_ref (connection
);
830 if (daemon
->next_minor_id
== G_MAXUINT32
)
832 daemon
->next_minor_id
= 0;
833 daemon
->next_major_id
++;
836 daemon
->next_minor_id
++;
838 g_object_set_data (G_OBJECT (connection
), "client", client
);
839 g_hash_table_insert (daemon
->clients
, client
->id
, client
);
841 g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (daemon
), connection
,
842 "/org/freedesktop/DBus", &error
);
843 g_assert_no_error (error
);
845 g_signal_connect (connection
, "closed", G_CALLBACK (connection_closed
), client
);
846 g_dbus_connection_add_filter (connection
,
850 send_name_owner_changed (daemon
, client
->id
, NULL
, client
->id
);
856 client_free (Client
*client
)
858 GDBusDaemon
*daemon
= client
->daemon
;
861 g_dbus_interface_skeleton_unexport_from_connection (G_DBUS_INTERFACE_SKELETON (daemon
),
864 g_hash_table_remove (daemon
->clients
, client
->id
);
866 names
= g_hash_table_get_values (daemon
->names
);
867 for (l
= names
; l
!= NULL
; l
= l
->next
)
869 Name
*name
= l
->data
;
873 if (name
->owner
&& name
->owner
->client
== client
)
874 name_release_owner (name
);
876 name_unqueue_owner (name
, client
);
882 send_name_owner_changed (daemon
, client
->id
, client
->id
, NULL
);
884 g_object_unref (client
->connection
);
886 for (l
= client
->matches
; l
!= NULL
; l
= l
->next
)
887 match_free (l
->data
);
888 g_list_free (client
->matches
);
895 idle_timeout_cb (gpointer user_data
)
897 GDBusDaemon
*daemon
= user_data
;
901 g_signal_emit (daemon
,
902 g_dbus_daemon_signals
[SIGNAL_IDLE_TIMEOUT
],
905 return G_SOURCE_REMOVE
;
909 connection_closed (GDBusConnection
*connection
,
910 gboolean remote_peer_vanished
,
914 GDBusDaemon
*daemon
= client
->daemon
;
916 client_free (client
);
918 if (g_hash_table_size (daemon
->clients
) == 0)
919 daemon
->timeout
= g_timeout_add (IDLE_TIMEOUT_MSEC
,
925 handle_add_match (_GFreedesktopDBus
*object
,
926 GDBusMethodInvocation
*invocation
,
927 const gchar
*arg_rule
)
929 Client
*client
= g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation
)), "client");
932 match
= match_new (arg_rule
);
935 g_dbus_method_invocation_return_error (invocation
,
936 G_DBUS_ERROR
, G_DBUS_ERROR_MATCH_RULE_INVALID
,
937 "Invalid rule: %s", arg_rule
);
940 client
->matches
= g_list_prepend (client
->matches
, match
);
941 _g_freedesktop_dbus_complete_add_match (object
, invocation
);
947 handle_get_connection_selinux_security_context (_GFreedesktopDBus
*object
,
948 GDBusMethodInvocation
*invocation
,
949 const gchar
*arg_name
)
951 g_dbus_method_invocation_return_error (invocation
,
952 G_DBUS_ERROR
, G_DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN
,
953 "selinux context not supported");
954 _g_freedesktop_dbus_complete_get_connection_selinux_security_context (object
, invocation
, "");
959 handle_get_connection_unix_process_id (_GFreedesktopDBus
*object
,
960 GDBusMethodInvocation
*invocation
,
961 const gchar
*arg_name
)
963 g_dbus_method_invocation_return_error (invocation
,
964 G_DBUS_ERROR
, G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN
,
965 "connection pid not supported");
970 handle_get_connection_unix_user (_GFreedesktopDBus
*object
,
971 GDBusMethodInvocation
*invocation
,
972 const gchar
*arg_name
)
974 g_dbus_method_invocation_return_error (invocation
,
975 G_DBUS_ERROR
, G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN
,
976 "connection user not supported");
981 handle_get_id (_GFreedesktopDBus
*object
,
982 GDBusMethodInvocation
*invocation
)
984 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
985 _g_freedesktop_dbus_complete_get_id (object
, invocation
,
991 handle_get_name_owner (_GFreedesktopDBus
*object
,
992 GDBusMethodInvocation
*invocation
,
993 const gchar
*arg_name
)
995 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
998 if (strcmp (arg_name
, DBUS_SERVICE_NAME
) == 0)
1000 _g_freedesktop_dbus_complete_get_name_owner (object
, invocation
, DBUS_SERVICE_NAME
);
1004 if (arg_name
[0] == ':')
1006 if (g_hash_table_lookup (daemon
->clients
, arg_name
) == NULL
)
1007 g_dbus_method_invocation_return_error (invocation
,
1008 G_DBUS_ERROR
, G_DBUS_ERROR_NAME_HAS_NO_OWNER
,
1009 "Could not get owner of name '%s': no such name", arg_name
);
1011 _g_freedesktop_dbus_complete_get_name_owner (object
, invocation
, arg_name
);
1015 name
= name_lookup (daemon
, arg_name
);
1016 if (name
== NULL
|| name
->owner
== NULL
)
1018 g_dbus_method_invocation_return_error (invocation
,
1019 G_DBUS_ERROR
, G_DBUS_ERROR_NAME_HAS_NO_OWNER
,
1020 "Could not get owner of name '%s': no such name", arg_name
);
1024 _g_freedesktop_dbus_complete_get_name_owner (object
, invocation
, name
->owner
->client
->id
);
1029 handle_hello (_GFreedesktopDBus
*object
,
1030 GDBusMethodInvocation
*invocation
)
1032 Client
*client
= g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation
)), "client");
1033 _g_freedesktop_dbus_complete_hello (object
, invocation
, client
->id
);
1035 g_dbus_connection_emit_signal (client
->connection
,
1036 NULL
, "/org/freedesktop/DBus",
1037 "org.freedesktop.DBus", "NameAcquired",
1038 g_variant_new ("(s)",
1045 handle_list_activatable_names (_GFreedesktopDBus
*object
,
1046 GDBusMethodInvocation
*invocation
)
1048 const char *names
[] = { NULL
};
1050 _g_freedesktop_dbus_complete_list_activatable_names (object
,
1057 handle_list_names (_GFreedesktopDBus
*object
,
1058 GDBusMethodInvocation
*invocation
)
1060 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1062 GList
*clients
, *names
, *l
;
1064 array
= g_ptr_array_new ();
1066 clients
= g_hash_table_get_values (daemon
->clients
);
1067 for (l
= clients
; l
!= NULL
; l
= l
->next
)
1069 Client
*client
= l
->data
;
1071 g_ptr_array_add (array
, client
->id
);
1074 g_list_free (clients
);
1076 names
= g_hash_table_get_values (daemon
->names
);
1077 for (l
= names
; l
!= NULL
; l
= l
->next
)
1079 Name
*name
= l
->data
;
1081 g_ptr_array_add (array
, name
->name
);
1084 g_list_free (names
);
1086 g_ptr_array_add (array
, NULL
);
1088 _g_freedesktop_dbus_complete_list_names (object
,
1090 (const gchar
* const*)array
->pdata
);
1091 g_ptr_array_free (array
, TRUE
);
1096 handle_list_queued_owners (_GFreedesktopDBus
*object
,
1097 GDBusMethodInvocation
*invocation
,
1098 const gchar
*arg_name
)
1100 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1105 array
= g_ptr_array_new ();
1107 name
= name_lookup (daemon
, arg_name
);
1108 if (name
&& name
->owner
)
1110 for (l
= name
->queue
; l
!= NULL
; l
= l
->next
)
1112 Client
*client
= l
->data
;
1114 g_ptr_array_add (array
, client
->id
);
1118 g_ptr_array_add (array
, NULL
);
1120 _g_freedesktop_dbus_complete_list_queued_owners (object
,
1122 (const gchar
* const*)array
->pdata
);
1123 g_ptr_array_free (array
, TRUE
);
1128 handle_name_has_owner (_GFreedesktopDBus
*object
,
1129 GDBusMethodInvocation
*invocation
,
1130 const gchar
*arg_name
)
1132 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1136 name
= name_lookup (daemon
, arg_name
);
1137 client
= g_hash_table_lookup (daemon
->clients
, arg_name
);
1139 _g_freedesktop_dbus_complete_name_has_owner (object
, invocation
,
1140 name
!= NULL
|| client
!= NULL
);
1145 handle_release_name (_GFreedesktopDBus
*object
,
1146 GDBusMethodInvocation
*invocation
,
1147 const gchar
*arg_name
)
1149 Client
*client
= g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation
)), "client");
1150 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1154 if (!g_dbus_is_name (arg_name
))
1156 g_dbus_method_invocation_return_error (invocation
,
1157 G_DBUS_ERROR
, G_DBUS_ERROR_INVALID_ARGS
,
1158 "Given bus name \"%s\" is not valid", arg_name
);
1162 if (*arg_name
== ':')
1164 g_dbus_method_invocation_return_error (invocation
,
1165 G_DBUS_ERROR
, G_DBUS_ERROR_INVALID_ARGS
,
1166 "Cannot release a service starting with ':' such as \"%s\"", arg_name
);
1170 if (strcmp (arg_name
, DBUS_SERVICE_NAME
) == 0)
1172 g_dbus_method_invocation_return_error (invocation
,
1173 G_DBUS_ERROR
, G_DBUS_ERROR_INVALID_ARGS
,
1174 "Cannot release a service named " DBUS_SERVICE_NAME
", because that is owned by the bus");
1178 name
= name_lookup (daemon
, arg_name
);
1181 result
= DBUS_RELEASE_NAME_REPLY_NON_EXISTENT
;
1182 else if (name
->owner
&& name
->owner
->client
== client
)
1184 name_release_owner (name
);
1185 result
= DBUS_RELEASE_NAME_REPLY_RELEASED
;
1187 else if (name_unqueue_owner (name
, client
))
1188 result
= DBUS_RELEASE_NAME_REPLY_RELEASED
;
1190 result
= DBUS_RELEASE_NAME_REPLY_NOT_OWNER
;
1192 _g_freedesktop_dbus_complete_release_name (object
, invocation
, result
);
1197 handle_reload_config (_GFreedesktopDBus
*object
,
1198 GDBusMethodInvocation
*invocation
)
1200 _g_freedesktop_dbus_complete_reload_config (object
, invocation
);
1205 handle_update_activation_environment (_GFreedesktopDBus
*object
,
1206 GDBusMethodInvocation
*invocation
,
1207 GVariant
*arg_environment
)
1209 g_dbus_method_invocation_return_error (invocation
,
1210 G_DBUS_ERROR
, G_DBUS_ERROR_FAILED
,
1211 "UpdateActivationEnvironment not implemented");
1216 handle_remove_match (_GFreedesktopDBus
*object
,
1217 GDBusMethodInvocation
*invocation
,
1218 const gchar
*arg_rule
)
1220 Client
*client
= g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation
)), "client");
1221 Match
*match
, *other_match
;
1224 match
= match_new (arg_rule
);
1227 g_dbus_method_invocation_return_error (invocation
,
1228 G_DBUS_ERROR
, G_DBUS_ERROR_MATCH_RULE_INVALID
,
1229 "Invalid rule: %s", arg_rule
);
1232 for (l
= client
->matches
; l
!= NULL
; l
= l
->next
)
1234 other_match
= l
->data
;
1235 if (match_equal (match
, other_match
))
1237 match_free (other_match
);
1238 client
->matches
= g_list_delete_link (client
->matches
, l
);
1244 g_dbus_method_invocation_return_error (invocation
,
1245 G_DBUS_ERROR
, G_DBUS_ERROR_MATCH_RULE_NOT_FOUND
,
1246 "The given match rule wasn't found and can't be removed");
1248 _g_freedesktop_dbus_complete_remove_match (object
, invocation
);
1257 handle_request_name (_GFreedesktopDBus
*object
,
1258 GDBusMethodInvocation
*invocation
,
1259 const gchar
*arg_name
,
1262 Client
*client
= g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation
)), "client");
1263 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1268 if (!g_dbus_is_name (arg_name
))
1270 g_dbus_method_invocation_return_error (invocation
,
1271 G_DBUS_ERROR
, G_DBUS_ERROR_INVALID_ARGS
,
1272 "Requested bus name \"%s\" is not valid", arg_name
);
1276 if (*arg_name
== ':')
1278 g_dbus_method_invocation_return_error (invocation
,
1279 G_DBUS_ERROR
, G_DBUS_ERROR_INVALID_ARGS
,
1280 "Cannot acquire a service starting with ':' such as \"%s\"", arg_name
);
1284 if (strcmp (arg_name
, DBUS_SERVICE_NAME
) == 0)
1286 g_dbus_method_invocation_return_error (invocation
,
1287 G_DBUS_ERROR
, G_DBUS_ERROR_INVALID_ARGS
,
1288 "Cannot acquire a service named " DBUS_SERVICE_NAME
", because that is reserved");
1292 name
= name_ensure (daemon
, arg_name
);
1293 if (name
->owner
== NULL
)
1295 owner
= name_owner_new (client
, flags
);
1296 name_replace_owner (name
, owner
);
1298 result
= DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER
;
1300 else if (name
->owner
&& name
->owner
->client
== client
)
1302 name
->owner
->flags
= flags
;
1303 result
= DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER
;
1305 else if ((flags
& DBUS_NAME_FLAG_DO_NOT_QUEUE
) &&
1306 (!(flags
& DBUS_NAME_FLAG_REPLACE_EXISTING
) ||
1307 !(name
->owner
->flags
& DBUS_NAME_FLAG_ALLOW_REPLACEMENT
)))
1309 /* Unqueue if queued */
1310 name_unqueue_owner (name
, client
);
1311 result
= DBUS_REQUEST_NAME_REPLY_EXISTS
;
1313 else if (!(flags
& DBUS_NAME_FLAG_DO_NOT_QUEUE
) &&
1314 (!(flags
& DBUS_NAME_FLAG_REPLACE_EXISTING
) ||
1315 !(name
->owner
->flags
& DBUS_NAME_FLAG_ALLOW_REPLACEMENT
)))
1317 /* Queue the connection */
1318 owner
= name_owner_new (client
, flags
);
1319 name_queue_owner (name
, owner
);
1320 result
= DBUS_REQUEST_NAME_REPLY_IN_QUEUE
;
1324 /* Replace the current owner */
1326 owner
= name_owner_new (client
, flags
);
1327 name_replace_owner (name
, owner
);
1329 result
= DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER
;
1334 _g_freedesktop_dbus_complete_request_name (object
, invocation
, result
);
1339 handle_start_service_by_name (_GFreedesktopDBus
*object
,
1340 GDBusMethodInvocation
*invocation
,
1341 const gchar
*arg_name
,
1344 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1347 name
= name_lookup (daemon
, arg_name
);
1349 _g_freedesktop_dbus_complete_start_service_by_name (object
, invocation
,
1350 DBUS_START_REPLY_ALREADY_RUNNING
);
1352 g_dbus_method_invocation_return_error (invocation
,
1353 G_DBUS_ERROR
, G_DBUS_ERROR_SERVICE_UNKNOWN
,
1354 "No support for activation for name: %s", arg_name
);
1361 return_error (Client
*client
, GDBusMessage
*message
,
1364 const gchar
*format
,
1367 GDBusMessage
*reply
;
1369 char *error_message
;
1371 gchar
*dbus_error_name
;
1373 va_start (var_args
, format
);
1374 error_message
= g_strdup_vprintf (format
, var_args
);
1377 error
= g_error_new_literal (domain
, code
, "");
1378 dbus_error_name
= g_dbus_error_encode_gerror (error
);
1380 reply
= g_dbus_message_new_method_error_literal (message
,
1384 g_error_free (error
);
1385 g_free (dbus_error_name
);
1386 g_free (error_message
);
1388 if (!g_dbus_connection_send_message (client
->connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
))
1389 g_warning ("Error sending reply");
1390 g_object_unref (reply
);
1393 static GDBusMessage
*
1394 route_message (Client
*source_client
, GDBusMessage
*message
)
1397 Client
*dest_client
;
1398 GDBusDaemon
*daemon
;
1400 daemon
= source_client
->daemon
;
1403 dest
= g_dbus_message_get_destination (message
);
1404 if (dest
!= NULL
&& strcmp (dest
, DBUS_SERVICE_NAME
) != 0)
1406 dest_client
= g_hash_table_lookup (daemon
->clients
, dest
);
1408 if (dest_client
== NULL
)
1411 name
= name_lookup (daemon
, dest
);
1412 if (name
&& name
->owner
)
1413 dest_client
= name
->owner
->client
;
1416 if (dest_client
== NULL
)
1418 if (g_dbus_message_get_message_type (message
) == G_DBUS_MESSAGE_TYPE_METHOD_CALL
)
1419 return_error (source_client
, message
,
1420 G_DBUS_ERROR
, G_DBUS_ERROR_SERVICE_UNKNOWN
,
1421 "The name %s is unknown", dest
);
1425 GError
*error
= NULL
;
1427 if (!g_dbus_connection_send_message (dest_client
->connection
, message
, G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL
, NULL
, &error
))
1429 g_warning ("Error forwarding message: %s", error
->message
);
1430 g_error_free (error
);
1435 broadcast_message (daemon
, message
, dest_client
!= NULL
, TRUE
, dest_client
);
1437 /* Swallow messages not for the bus */
1438 if (dest
== NULL
|| strcmp (dest
, DBUS_SERVICE_NAME
) != 0)
1440 g_object_unref (message
);
1447 static GDBusMessage
*
1448 copy_if_locked (GDBusMessage
*message
)
1450 if (g_dbus_message_get_locked (message
))
1452 GDBusMessage
*copy
= g_dbus_message_copy (message
, NULL
);
1453 g_object_unref (message
);
1459 static GDBusMessage
*
1460 filter_function (GDBusConnection
*connection
,
1461 GDBusMessage
*message
,
1465 Client
*client
= user_data
;
1466 char *types
[] = {"invalid", "method_call", "method_return", "error", "signal" };
1469 g_printerr ("%s%s %s %d(%d) sender: %s destination: %s %s %s.%s\n",
1471 incoming
? "->" : "<-",
1472 types
[g_dbus_message_get_message_type (message
)],
1473 g_dbus_message_get_serial (message
),
1474 g_dbus_message_get_reply_serial (message
),
1475 g_dbus_message_get_sender (message
),
1476 g_dbus_message_get_destination (message
),
1477 g_dbus_message_get_path (message
),
1478 g_dbus_message_get_interface (message
),
1479 g_dbus_message_get_member (message
));
1483 /* Ensure its not locked so we can set the sender */
1484 message
= copy_if_locked (message
);
1485 if (message
== NULL
)
1487 g_warning ("Failed to copy incoming message");
1490 g_dbus_message_set_sender (message
, client
->id
);
1492 return route_message (client
, message
);
1496 if (g_dbus_message_get_sender (message
) == NULL
)
1498 message
= copy_if_locked (message
);
1499 g_dbus_message_set_sender (message
, DBUS_SERVICE_NAME
);
1501 if (g_dbus_message_get_destination (message
) == NULL
)
1503 message
= copy_if_locked (message
);
1504 g_dbus_message_set_destination (message
, client
->id
);
1512 on_new_connection (GDBusServer
*server
,
1513 GDBusConnection
*connection
,
1516 GDBusDaemon
*daemon
= user_data
;
1518 g_dbus_connection_set_exit_on_close (connection
, FALSE
);
1520 if (daemon
->timeout
)
1522 g_source_remove (daemon
->timeout
);
1523 daemon
->timeout
= 0;
1526 client_new (daemon
, connection
);
1532 on_authorize_authenticated_peer (GDBusAuthObserver
*observer
,
1534 GCredentials
*credentials
,
1537 gboolean authorized
= TRUE
;
1539 if (credentials
!= NULL
)
1541 GCredentials
*own_credentials
;
1543 own_credentials
= g_credentials_new ();
1544 authorized
= g_credentials_is_same_user (credentials
, own_credentials
, NULL
);
1545 g_object_unref (own_credentials
);
1552 g_dbus_daemon_finalize (GObject
*object
)
1554 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1557 if (daemon
->timeout
)
1558 g_source_remove (daemon
->timeout
);
1560 clients
= g_hash_table_get_values (daemon
->clients
);
1561 for (l
= clients
; l
!= NULL
; l
= l
->next
)
1562 client_free (l
->data
);
1563 g_list_free (clients
);
1565 g_assert (g_hash_table_size (daemon
->clients
) == 0);
1566 g_assert (g_hash_table_size (daemon
->names
) == 0);
1568 g_hash_table_destroy (daemon
->clients
);
1569 g_hash_table_destroy (daemon
->names
);
1571 g_object_unref (daemon
->server
);
1575 g_rmdir (daemon
->tmpdir
);
1576 g_free (daemon
->tmpdir
);
1579 g_free (daemon
->guid
);
1580 g_free (daemon
->address
);
1582 G_OBJECT_CLASS (g_dbus_daemon_parent_class
)->finalize (object
);
1586 g_dbus_daemon_init (GDBusDaemon
*daemon
)
1588 daemon
->next_major_id
= 1;
1589 daemon
->clients
= g_hash_table_new_full (g_str_hash
, g_str_equal
, NULL
, NULL
);
1590 daemon
->names
= g_hash_table_new_full (g_str_hash
, g_str_equal
, NULL
, NULL
);
1591 daemon
->guid
= g_dbus_generate_guid ();
1595 initable_init (GInitable
*initable
,
1596 GCancellable
*cancellable
,
1599 GDBusDaemon
*daemon
= G_DBUS_DAEMON (initable
);
1600 GDBusAuthObserver
*observer
;
1601 GDBusServerFlags flags
;
1603 flags
= G_DBUS_SERVER_FLAGS_NONE
;
1604 if (daemon
->address
== NULL
)
1607 if (g_unix_socket_address_abstract_names_supported ())
1608 daemon
->address
= g_strdup ("unix:tmpdir=/tmp/gdbus-daemon");
1611 daemon
->tmpdir
= g_dir_make_tmp ("gdbus-daemon-XXXXXX", NULL
);
1612 daemon
->address
= g_strdup_printf ("unix:tmpdir=%s", daemon
->tmpdir
);
1615 daemon
->address
= g_strdup ("nonce-tcp:");
1616 flags
|= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS
;
1620 observer
= g_dbus_auth_observer_new ();
1621 daemon
->server
= g_dbus_server_new_sync (daemon
->address
,
1627 if (daemon
->server
== NULL
)
1629 g_object_unref (observer
);
1634 g_dbus_server_start (daemon
->server
);
1636 g_signal_connect (daemon
->server
, "new-connection",
1637 G_CALLBACK (on_new_connection
),
1639 g_signal_connect (observer
,
1640 "authorize-authenticated-peer",
1641 G_CALLBACK (on_authorize_authenticated_peer
),
1644 g_object_unref (observer
);
1650 g_dbus_daemon_set_property (GObject
*object
,
1652 const GValue
*value
,
1655 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1660 g_free (daemon
->address
);
1661 daemon
->address
= g_value_dup_string (value
);
1665 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
1670 g_dbus_daemon_get_property (GObject
*object
,
1675 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1680 g_value_set_string (value
, daemon
->address
);
1684 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
1689 g_dbus_daemon_class_init (GDBusDaemonClass
*klass
)
1691 GObjectClass
*gobject_class
;
1693 gobject_class
= G_OBJECT_CLASS (klass
);
1694 gobject_class
->finalize
= g_dbus_daemon_finalize
;
1695 gobject_class
->set_property
= g_dbus_daemon_set_property
;
1696 gobject_class
->get_property
= g_dbus_daemon_get_property
;
1698 g_dbus_daemon_signals
[SIGNAL_IDLE_TIMEOUT
] =
1699 g_signal_new (I_("idle-timeout"),
1704 g_cclosure_marshal_VOID__VOID
,
1707 g_object_class_install_property (gobject_class
,
1709 g_param_spec_string ("address",
1711 "The address the bus should use",
1714 G_PARAM_CONSTRUCT_ONLY
|
1715 G_PARAM_STATIC_STRINGS
));
1719 g_dbus_daemon_iface_init (_GFreedesktopDBusIface
*iface
)
1721 iface
->handle_add_match
= handle_add_match
;
1722 iface
->handle_get_connection_selinux_security_context
= handle_get_connection_selinux_security_context
;
1723 iface
->handle_get_connection_unix_process_id
= handle_get_connection_unix_process_id
;
1724 iface
->handle_get_connection_unix_user
= handle_get_connection_unix_user
;
1725 iface
->handle_get_id
= handle_get_id
;
1726 iface
->handle_get_name_owner
= handle_get_name_owner
;
1727 iface
->handle_hello
= handle_hello
;
1728 iface
->handle_list_activatable_names
= handle_list_activatable_names
;
1729 iface
->handle_list_names
= handle_list_names
;
1730 iface
->handle_list_queued_owners
= handle_list_queued_owners
;
1731 iface
->handle_name_has_owner
= handle_name_has_owner
;
1732 iface
->handle_release_name
= handle_release_name
;
1733 iface
->handle_reload_config
= handle_reload_config
;
1734 iface
->handle_update_activation_environment
= handle_update_activation_environment
;
1735 iface
->handle_remove_match
= handle_remove_match
;
1736 iface
->handle_request_name
= handle_request_name
;
1737 iface
->handle_start_service_by_name
= handle_start_service_by_name
;
1741 initable_iface_init (GInitableIface
*initable_iface
)
1743 initable_iface
->init
= initable_init
;
1747 _g_dbus_daemon_new (const char *address
,
1748 GCancellable
*cancellable
,
1751 return g_initable_new (G_TYPE_DBUS_DAEMON
,
1759 _g_dbus_daemon_get_address (GDBusDaemon
*daemon
)
1761 return g_dbus_server_get_client_address (daemon
->server
);