8 #include <gio/gunixsocketaddress.h>
9 #include "gdbusdaemon.h"
11 #include "gdbus-daemon-generated.h"
13 #define DBUS_SERVICE_NAME "org.freedesktop.DBus"
16 #define DBUS_NAME_FLAG_ALLOW_REPLACEMENT 0x1 /**< Allow another service to become the primary owner if requested */
17 #define DBUS_NAME_FLAG_REPLACE_EXISTING 0x2 /**< Request to replace the current primary owner */
18 #define DBUS_NAME_FLAG_DO_NOT_QUEUE 0x4 /**< If we can not become the primary owner do not place us in the queue */
20 /* Replies to request for a name */
21 #define DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER 1 /**< Service has become the primary owner of the requested name */
22 #define DBUS_REQUEST_NAME_REPLY_IN_QUEUE 2 /**< Service could not become the primary owner and has been placed in the queue */
23 #define DBUS_REQUEST_NAME_REPLY_EXISTS 3 /**< Service is already in the queue */
24 #define DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER 4 /**< Service is already the primary owner */
26 /* Replies to releasing a name */
27 #define DBUS_RELEASE_NAME_REPLY_RELEASED 1 /**< Service was released from the given name */
28 #define DBUS_RELEASE_NAME_REPLY_NON_EXISTENT 2 /**< The given name does not exist on the bus */
29 #define DBUS_RELEASE_NAME_REPLY_NOT_OWNER 3 /**< Service is not an owner of the given name */
31 /* Replies to service starts */
32 #define DBUS_START_REPLY_SUCCESS 1 /**< Service was auto started */
33 #define DBUS_START_REPLY_ALREADY_RUNNING 2 /**< Service was already running */
35 #define IDLE_TIMEOUT_MSEC 3000
39 _GFreedesktopDBusSkeleton parent_instance
;
48 guint32 next_major_id
;
49 guint32 next_minor_id
;
52 struct _GDBusDaemonClass
54 _GFreedesktopDBusSkeletonClass parent_class
;
68 static guint g_dbus_daemon_signals
[NR_SIGNALS
];
71 static void initable_iface_init (GInitableIface
*initable_iface
);
72 static void g_dbus_daemon_iface_init (_GFreedesktopDBusIface
*iface
);
74 #define g_dbus_daemon_get_type _g_dbus_daemon_get_type
75 G_DEFINE_TYPE_WITH_CODE (GDBusDaemon
, g_dbus_daemon
, _G_TYPE_FREEDESKTOP_DBUS_SKELETON
,
76 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE
, initable_iface_init
)
77 G_IMPLEMENT_INTERFACE (_G_TYPE_FREEDESKTOP_DBUS
, g_dbus_daemon_iface_init
));
82 GDBusConnection
*connection
;
103 MATCH_ELEMENT_SENDER
,
104 MATCH_ELEMENT_INTERFACE
,
105 MATCH_ELEMENT_MEMBER
,
107 MATCH_ELEMENT_PATH_NAMESPACE
,
108 MATCH_ELEMENT_DESTINATION
,
109 MATCH_ELEMENT_ARG0NAMESPACE
,
110 MATCH_ELEMENT_EAVESDROP
,
112 MATCH_ELEMENT_ARGNPATH
,
123 GDBusMessageType type
;
125 MatchElement
*elements
;
128 static GDBusMessage
*filter_function (GDBusConnection
*connection
,
129 GDBusMessage
*message
,
132 static void connection_closed (GDBusConnection
*connection
,
133 gboolean remote_peer_vanished
,
138 name_owner_new (Client
*client
, guint32 flags
)
142 owner
= g_new0 (NameOwner
, 1);
143 owner
->client
= client
;
144 owner
->flags
= flags
;
149 name_owner_free (NameOwner
*owner
)
155 name_new (GDBusDaemon
*daemon
, const char *str
)
159 name
= g_new0 (Name
, 1);
161 name
->daemon
= daemon
;
162 name
->name
= g_strdup (str
);
164 g_hash_table_insert (daemon
->names
, name
->name
, name
);
170 name_ref (Name
*name
)
177 name_unref (Name
*name
)
179 if (--name
->refcount
== 0)
181 g_hash_table_remove (name
->daemon
->names
, name
->name
);
188 name_ensure (GDBusDaemon
*daemon
, const char *str
)
192 name
= g_hash_table_lookup (daemon
->names
, str
);
195 return name_ref (name
);
196 return name_new (daemon
, str
);
200 name_lookup (GDBusDaemon
*daemon
, const char *str
)
202 return g_hash_table_lookup (daemon
->names
, str
);
206 is_key (const char *key_start
, const char *key_end
, char *value
)
208 gsize len
= strlen (value
);
210 if (len
!= key_end
- key_start
)
213 return strncmp (key_start
, value
, len
) == 0;
217 parse_key (MatchElement
*element
, const char *key_start
, const char *key_end
)
221 if (is_key (key_start
, key_end
, "type"))
223 element
->type
= MATCH_ELEMENT_TYPE
;
225 else if (is_key (key_start
, key_end
, "sender"))
227 element
->type
= MATCH_ELEMENT_SENDER
;
229 else if (is_key (key_start
, key_end
, "interface"))
231 element
->type
= MATCH_ELEMENT_INTERFACE
;
233 else if (is_key (key_start
, key_end
, "member"))
235 element
->type
= MATCH_ELEMENT_MEMBER
;
237 else if (is_key (key_start
, key_end
, "path"))
239 element
->type
= MATCH_ELEMENT_PATH
;
241 else if (is_key (key_start
, key_end
, "path_namespace"))
243 element
->type
= MATCH_ELEMENT_PATH_NAMESPACE
;
245 else if (is_key (key_start
, key_end
, "destination"))
247 element
->type
= MATCH_ELEMENT_DESTINATION
;
249 else if (is_key (key_start
, key_end
, "arg0namespace"))
251 element
->type
= MATCH_ELEMENT_ARG0NAMESPACE
;
253 else if (is_key (key_start
, key_end
, "eavesdrop"))
255 element
->type
= MATCH_ELEMENT_EAVESDROP
;
257 else if (key_end
- key_start
> 3 && is_key (key_start
, key_start
+ 3, "arg"))
259 const char *digits
= key_start
+ 3;
260 const char *end_digits
= digits
;
262 while (end_digits
< key_end
&& g_ascii_isdigit (*end_digits
))
265 if (end_digits
== key_end
) /* argN */
267 element
->type
= MATCH_ELEMENT_ARGN
;
268 element
->arg
= atoi (digits
);
270 else if (is_key (end_digits
, key_end
, "path")) /* argNpath */
272 element
->type
= MATCH_ELEMENT_ARGNPATH
;
273 element
->arg
= atoi (digits
);
285 parse_value (MatchElement
*element
, const char *s
)
290 value
= g_string_new ("");
313 g_string_append_c (value
, *s
);
317 else if (quote_char
== '\\')
319 /* \ only counts as an escape if escaping a quote mark */
321 g_string_append_c (value
, '\\');
323 g_string_append_c (value
, *s
);
326 else /* quote_char == ' */
331 g_string_append_c (value
, *s
);
337 if (quote_char
== '\\')
338 g_string_append_c (value
, '\\');
339 else if (quote_char
== '\'')
341 g_string_free (value
, TRUE
);
345 element
->value
= g_string_free (value
, FALSE
);
350 match_new (const char *str
)
355 const char *key_start
;
357 MatchElement element
;
359 GDBusMessageType type
;
363 type
= G_DBUS_MESSAGE_TYPE_INVALID
;
364 elements
= g_array_new (TRUE
, TRUE
, sizeof (MatchElement
));
370 memset (&element
, 0, sizeof (element
));
372 /* Skip initial whitespace */
373 while (*p
&& g_ascii_isspace (*p
))
378 /* Read non-whitespace non-equals chars */
379 while (*p
&& *p
!= '=' && !g_ascii_isspace (*p
))
384 /* Skip any whitespace after key */
385 while (*p
&& g_ascii_isspace (*p
))
388 if (key_start
== key_end
)
389 continue; /* Allow trailing whitespace */
396 if (!parse_key (&element
, key_start
, key_end
))
399 p
= parse_value (&element
, p
);
403 if (element
.type
== MATCH_ELEMENT_EAVESDROP
)
405 if (strcmp (element
.value
, "true") == 0)
407 else if (strcmp (element
.value
, "false") == 0)
411 g_free (element
.value
);
414 g_free (element
.value
);
416 else if (element
.type
== MATCH_ELEMENT_TYPE
)
418 if (strcmp (element
.value
, "signal") == 0)
419 type
= G_DBUS_MESSAGE_TYPE_SIGNAL
;
420 else if (strcmp (element
.value
, "method_call") == 0)
421 type
= G_DBUS_MESSAGE_TYPE_METHOD_CALL
;
422 else if (strcmp (element
.value
, "method_return") == 0)
423 type
= G_DBUS_MESSAGE_TYPE_METHOD_RETURN
;
424 else if (strcmp (element
.value
, "error") == 0)
425 type
= G_DBUS_MESSAGE_TYPE_ERROR
;
428 g_free (element
.value
);
431 g_free (element
.value
);
434 g_array_append_val (elements
, element
);
437 match
= g_new0 (Match
, 1);
438 match
->n_elements
= elements
->len
;
439 match
->elements
= (MatchElement
*)g_array_free (elements
, FALSE
);
440 match
->eavesdrop
= eavesdrop
;
446 for (i
= 0; i
< elements
->len
; i
++)
447 g_free (g_array_index (elements
, MatchElement
, i
).value
);
448 g_array_free (elements
, TRUE
);
453 match_free (Match
*match
)
456 for (i
= 0; i
< match
->n_elements
; i
++)
457 g_free (match
->elements
[i
].value
);
458 g_free (match
->elements
);
463 match_equal (Match
*a
, Match
*b
)
467 if (a
->eavesdrop
!= b
->eavesdrop
)
469 if (a
->type
!= b
->type
)
471 if (a
->n_elements
!= b
->n_elements
)
473 for (i
= 0; i
< a
->n_elements
; i
++)
475 if (a
->elements
[i
].type
!= b
->elements
[i
].type
||
476 a
->elements
[i
].arg
!= b
->elements
[i
].arg
||
477 strcmp (a
->elements
[i
].value
, b
->elements
[i
].value
) != 0)
484 message_get_argN (GDBusMessage
*message
, int n
, gboolean allow_path
)
491 body
= g_dbus_message_get_body (message
);
493 if (body
!= NULL
&& g_variant_is_of_type (body
, G_VARIANT_TYPE_TUPLE
))
496 item
= g_variant_get_child_value (body
, n
);
497 if (g_variant_is_of_type (item
, G_VARIANT_TYPE_STRING
) ||
498 (allow_path
&& g_variant_is_of_type (item
, G_VARIANT_TYPE_OBJECT_PATH
)))
499 ret
= g_variant_get_string (item
, NULL
);
500 g_variant_unref (item
);
509 CHECK_TYPE_PATH_PREFIX
,
510 CHECK_TYPE_PATH_RELATED
,
511 CHECK_TYPE_NAMESPACE_PREFIX
515 match_matches (GDBusDaemon
*daemon
,
516 Match
*match
, GDBusMessage
*message
,
517 gboolean has_destination
)
519 MatchElement
*element
;
525 if (has_destination
&& !match
->eavesdrop
)
528 if (match
->type
!= G_DBUS_MESSAGE_TYPE_INVALID
&&
529 g_dbus_message_get_message_type (message
) != match
->type
)
532 for (i
= 0; i
< match
->n_elements
; i
++)
534 element
= &match
->elements
[i
];
535 check_type
= CHECK_TYPE_STRING
;
536 switch (element
->type
)
538 case MATCH_ELEMENT_SENDER
:
539 check_type
= CHECK_TYPE_NAME
;
540 value
= g_dbus_message_get_sender (message
);
542 value
= DBUS_SERVICE_NAME
;
544 case MATCH_ELEMENT_DESTINATION
:
545 check_type
= CHECK_TYPE_NAME
;
546 value
= g_dbus_message_get_destination (message
);
548 case MATCH_ELEMENT_INTERFACE
:
549 value
= g_dbus_message_get_interface (message
);
551 case MATCH_ELEMENT_MEMBER
:
552 value
= g_dbus_message_get_member (message
);
554 case MATCH_ELEMENT_PATH
:
555 value
= g_dbus_message_get_path (message
);
557 case MATCH_ELEMENT_PATH_NAMESPACE
:
558 check_type
= CHECK_TYPE_PATH_PREFIX
;
559 value
= g_dbus_message_get_path (message
);
561 case MATCH_ELEMENT_ARG0NAMESPACE
:
562 check_type
= CHECK_TYPE_NAMESPACE_PREFIX
;
563 value
= message_get_argN (message
, 0, FALSE
);
565 case MATCH_ELEMENT_ARGN
:
566 value
= message_get_argN (message
, element
->arg
, FALSE
);
568 case MATCH_ELEMENT_ARGNPATH
:
569 check_type
= CHECK_TYPE_PATH_RELATED
;
570 value
= message_get_argN (message
, element
->arg
, TRUE
);
573 case MATCH_ELEMENT_TYPE
:
574 case MATCH_ELEMENT_EAVESDROP
:
575 g_assert_not_reached ();
583 case CHECK_TYPE_STRING
:
584 if (strcmp (element
->value
, value
) != 0)
587 case CHECK_TYPE_NAME
:
588 name
= name_lookup (daemon
, element
->value
);
589 if (name
!= NULL
&& name
->owner
!= NULL
)
591 if (strcmp (name
->owner
->client
->id
, value
) != 0)
594 else if (strcmp (element
->value
, value
) != 0)
597 case CHECK_TYPE_PATH_PREFIX
:
598 len
= strlen (element
->value
);
600 /* Make sure to handle the case of element->value == '/'. */
604 /* Fail if there's no prefix match, or if the prefix match doesn't
605 * finish at the end of or at a separator in the @value. */
606 if (!g_str_has_prefix (value
, element
->value
))
608 if (value
[len
] != 0 && value
[len
] != '/')
612 case CHECK_TYPE_PATH_RELATED
:
613 len
= strlen (element
->value
);
614 len2
= strlen (value
);
616 if (!(strcmp (value
, element
->value
) == 0 ||
617 (len2
> 0 && value
[len2
-1] == '/' && g_str_has_prefix (element
->value
, value
)) ||
618 (len
> 0 && element
->value
[len
-1] == '/' && g_str_has_prefix (value
, element
->value
))))
621 case CHECK_TYPE_NAMESPACE_PREFIX
:
622 len
= strlen (element
->value
);
623 if (!(g_str_has_prefix (value
, element
->value
) &&
624 (value
[len
] == 0 || value
[len
] == '.')))
628 g_assert_not_reached ();
636 broadcast_message (GDBusDaemon
*daemon
,
637 GDBusMessage
*message
,
638 gboolean has_destination
,
639 gboolean preserve_serial
,
642 GList
*clients
, *l
, *ll
;
645 clients
= g_hash_table_get_values (daemon
->clients
);
646 for (l
= clients
; l
!= NULL
; l
= l
->next
)
648 Client
*client
= l
->data
;
650 if (client
== not_to
)
653 for (ll
= client
->matches
; ll
!= NULL
; ll
= ll
->next
)
655 Match
*match
= ll
->data
;
657 if (match_matches (daemon
, match
, message
, has_destination
))
663 copy
= g_dbus_message_copy (message
, NULL
);
666 g_dbus_connection_send_message (client
->connection
, copy
,
667 preserve_serial
?G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL
:0, NULL
, NULL
);
668 g_object_unref (copy
);
673 g_list_free (clients
);
677 send_name_owner_changed (GDBusDaemon
*daemon
,
679 const char *old_owner
,
680 const char *new_owner
)
682 GDBusMessage
*signal_message
;
684 signal_message
= g_dbus_message_new_signal ("/org/freedesktop/DBus",
685 "org.freedesktop.DBus",
687 g_dbus_message_set_body (signal_message
,
688 g_variant_new ("(sss)",
690 old_owner
? old_owner
: "",
691 new_owner
? new_owner
: ""));
693 broadcast_message (daemon
, signal_message
, FALSE
, FALSE
, NULL
);
694 g_object_unref (signal_message
);
699 name_unqueue_owner (Name
*name
, Client
*client
)
703 for (l
= name
->queue
; l
!= NULL
; l
= l
->next
)
705 NameOwner
*other
= l
->data
;
707 if (other
->client
== client
)
709 name
->queue
= g_list_delete_link (name
->queue
, l
);
711 name_owner_free (other
);
720 name_replace_owner (Name
*name
, NameOwner
*owner
)
722 GDBusDaemon
*daemon
= name
->daemon
;
723 NameOwner
*old_owner
;
724 char *old_name
= NULL
, *new_name
= NULL
;
725 Client
*new_client
= NULL
;
728 new_client
= owner
->client
;
732 old_owner
= name
->owner
;
735 Client
*old_client
= old_owner
->client
;
737 g_assert (old_owner
->client
!= new_client
);
739 g_dbus_connection_emit_signal (old_client
->connection
,
740 NULL
, "/org/freedesktop/DBus",
741 "org.freedesktop.DBus", "NameLost",
742 g_variant_new ("(s)",
745 old_name
= g_strdup (old_client
->id
);
746 if (old_owner
->flags
& DBUS_NAME_FLAG_DO_NOT_QUEUE
)
749 name_owner_free (old_owner
);
752 name
->queue
= g_list_prepend (name
->queue
, old_owner
);
758 name_unqueue_owner (name
, owner
->client
);
760 new_name
= new_client
->id
;
762 g_dbus_connection_emit_signal (new_client
->connection
,
763 NULL
, "/org/freedesktop/DBus",
764 "org.freedesktop.DBus", "NameAcquired",
765 g_variant_new ("(s)",
769 send_name_owner_changed (daemon
, name
->name
, old_name
, new_name
);
777 name_release_owner (Name
*name
)
779 NameOwner
*next_owner
= NULL
;
783 /* Will someone else take over? */
786 next_owner
= name
->queue
->data
;
788 name
->queue
= g_list_delete_link (name
->queue
, name
->queue
);
791 name
->owner
->flags
|= DBUS_NAME_FLAG_DO_NOT_QUEUE
;
792 name_replace_owner (name
, next_owner
);
798 name_queue_owner (Name
*name
, NameOwner
*owner
)
802 for (l
= name
->queue
; l
!= NULL
; l
= l
->next
)
804 NameOwner
*other
= l
->data
;
806 if (other
->client
== owner
->client
)
808 other
->flags
= owner
->flags
;
809 name_owner_free (owner
);
814 name
->queue
= g_list_append (name
->queue
, owner
);
819 client_new (GDBusDaemon
*daemon
, GDBusConnection
*connection
)
822 GError
*error
= NULL
;
824 client
= g_new0 (Client
, 1);
825 client
->daemon
= daemon
;
826 client
->id
= g_strdup_printf (":%d.%d", daemon
->next_major_id
, daemon
->next_minor_id
);
827 client
->connection
= g_object_ref (connection
);
829 if (daemon
->next_minor_id
== G_MAXUINT32
)
831 daemon
->next_minor_id
= 0;
832 daemon
->next_major_id
++;
835 daemon
->next_minor_id
++;
837 g_object_set_data (G_OBJECT (connection
), "client", client
);
838 g_hash_table_insert (daemon
->clients
, client
->id
, client
);
840 g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (daemon
), connection
,
841 "/org/freedesktop/DBus", &error
);
842 g_assert_no_error (error
);
844 g_signal_connect (connection
, "closed", G_CALLBACK (connection_closed
), client
);
845 g_dbus_connection_add_filter (connection
,
849 send_name_owner_changed (daemon
, client
->id
, NULL
, client
->id
);
855 client_free (Client
*client
)
857 GDBusDaemon
*daemon
= client
->daemon
;
860 g_dbus_interface_skeleton_unexport_from_connection (G_DBUS_INTERFACE_SKELETON (daemon
),
863 g_hash_table_remove (daemon
->clients
, client
->id
);
865 names
= g_hash_table_get_values (daemon
->names
);
866 for (l
= names
; l
!= NULL
; l
= l
->next
)
868 Name
*name
= l
->data
;
872 if (name
->owner
&& name
->owner
->client
== client
)
873 name_release_owner (name
);
875 name_unqueue_owner (name
, client
);
881 send_name_owner_changed (daemon
, client
->id
, client
->id
, NULL
);
883 g_object_unref (client
->connection
);
885 for (l
= client
->matches
; l
!= NULL
; l
= l
->next
)
886 match_free (l
->data
);
887 g_list_free (client
->matches
);
894 idle_timeout_cb (gpointer user_data
)
896 GDBusDaemon
*daemon
= user_data
;
900 g_signal_emit (daemon
,
901 g_dbus_daemon_signals
[SIGNAL_IDLE_TIMEOUT
],
904 return G_SOURCE_REMOVE
;
908 connection_closed (GDBusConnection
*connection
,
909 gboolean remote_peer_vanished
,
913 GDBusDaemon
*daemon
= client
->daemon
;
915 client_free (client
);
917 if (g_hash_table_size (daemon
->clients
) == 0)
918 daemon
->timeout
= g_timeout_add (IDLE_TIMEOUT_MSEC
,
924 handle_add_match (_GFreedesktopDBus
*object
,
925 GDBusMethodInvocation
*invocation
,
926 const gchar
*arg_rule
)
928 Client
*client
= g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation
)), "client");
931 match
= match_new (arg_rule
);
934 g_dbus_method_invocation_return_error (invocation
,
935 G_DBUS_ERROR
, G_DBUS_ERROR_MATCH_RULE_INVALID
,
936 "Invalid rule: %s", arg_rule
);
939 client
->matches
= g_list_prepend (client
->matches
, match
);
940 _g_freedesktop_dbus_complete_add_match (object
, invocation
);
946 handle_get_connection_selinux_security_context (_GFreedesktopDBus
*object
,
947 GDBusMethodInvocation
*invocation
,
948 const gchar
*arg_name
)
950 g_dbus_method_invocation_return_error (invocation
,
951 G_DBUS_ERROR
, G_DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN
,
952 "selinux context not supported");
953 _g_freedesktop_dbus_complete_get_connection_selinux_security_context (object
, invocation
, "");
958 handle_get_connection_unix_process_id (_GFreedesktopDBus
*object
,
959 GDBusMethodInvocation
*invocation
,
960 const gchar
*arg_name
)
962 g_dbus_method_invocation_return_error (invocation
,
963 G_DBUS_ERROR
, G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN
,
964 "connection pid not supported");
969 handle_get_connection_unix_user (_GFreedesktopDBus
*object
,
970 GDBusMethodInvocation
*invocation
,
971 const gchar
*arg_name
)
973 g_dbus_method_invocation_return_error (invocation
,
974 G_DBUS_ERROR
, G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN
,
975 "connection user not supported");
980 handle_get_id (_GFreedesktopDBus
*object
,
981 GDBusMethodInvocation
*invocation
)
983 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
984 _g_freedesktop_dbus_complete_get_id (object
, invocation
,
990 handle_get_name_owner (_GFreedesktopDBus
*object
,
991 GDBusMethodInvocation
*invocation
,
992 const gchar
*arg_name
)
994 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
997 if (strcmp (arg_name
, DBUS_SERVICE_NAME
) == 0)
999 _g_freedesktop_dbus_complete_get_name_owner (object
, invocation
, DBUS_SERVICE_NAME
);
1003 if (arg_name
[0] == ':')
1005 if (g_hash_table_lookup (daemon
->clients
, arg_name
) == NULL
)
1006 g_dbus_method_invocation_return_error (invocation
,
1007 G_DBUS_ERROR
, G_DBUS_ERROR_NAME_HAS_NO_OWNER
,
1008 "Could not get owner of name '%s': no such name", arg_name
);
1010 _g_freedesktop_dbus_complete_get_name_owner (object
, invocation
, arg_name
);
1014 name
= name_lookup (daemon
, arg_name
);
1015 if (name
== NULL
|| name
->owner
== NULL
)
1017 g_dbus_method_invocation_return_error (invocation
,
1018 G_DBUS_ERROR
, G_DBUS_ERROR_NAME_HAS_NO_OWNER
,
1019 "Could not get owner of name '%s': no such name", arg_name
);
1023 _g_freedesktop_dbus_complete_get_name_owner (object
, invocation
, name
->owner
->client
->id
);
1028 handle_hello (_GFreedesktopDBus
*object
,
1029 GDBusMethodInvocation
*invocation
)
1031 Client
*client
= g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation
)), "client");
1032 _g_freedesktop_dbus_complete_hello (object
, invocation
, client
->id
);
1034 g_dbus_connection_emit_signal (client
->connection
,
1035 NULL
, "/org/freedesktop/DBus",
1036 "org.freedesktop.DBus", "NameAcquired",
1037 g_variant_new ("(s)",
1044 handle_list_activatable_names (_GFreedesktopDBus
*object
,
1045 GDBusMethodInvocation
*invocation
)
1047 const char *names
[] = { NULL
};
1049 _g_freedesktop_dbus_complete_list_activatable_names (object
,
1056 handle_list_names (_GFreedesktopDBus
*object
,
1057 GDBusMethodInvocation
*invocation
)
1059 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1061 GList
*clients
, *names
, *l
;
1063 array
= g_ptr_array_new ();
1065 clients
= g_hash_table_get_values (daemon
->clients
);
1066 for (l
= clients
; l
!= NULL
; l
= l
->next
)
1068 Client
*client
= l
->data
;
1070 g_ptr_array_add (array
, client
->id
);
1073 g_list_free (clients
);
1075 names
= g_hash_table_get_values (daemon
->names
);
1076 for (l
= names
; l
!= NULL
; l
= l
->next
)
1078 Name
*name
= l
->data
;
1080 g_ptr_array_add (array
, name
->name
);
1083 g_list_free (names
);
1085 g_ptr_array_add (array
, NULL
);
1087 _g_freedesktop_dbus_complete_list_names (object
,
1089 (const gchar
* const*)array
->pdata
);
1090 g_ptr_array_free (array
, TRUE
);
1095 handle_list_queued_owners (_GFreedesktopDBus
*object
,
1096 GDBusMethodInvocation
*invocation
,
1097 const gchar
*arg_name
)
1099 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1104 array
= g_ptr_array_new ();
1106 name
= name_lookup (daemon
, arg_name
);
1107 if (name
&& name
->owner
)
1109 for (l
= name
->queue
; l
!= NULL
; l
= l
->next
)
1111 Client
*client
= l
->data
;
1113 g_ptr_array_add (array
, client
->id
);
1117 g_ptr_array_add (array
, NULL
);
1119 _g_freedesktop_dbus_complete_list_queued_owners (object
,
1121 (const gchar
* const*)array
->pdata
);
1122 g_ptr_array_free (array
, TRUE
);
1127 handle_name_has_owner (_GFreedesktopDBus
*object
,
1128 GDBusMethodInvocation
*invocation
,
1129 const gchar
*arg_name
)
1131 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1135 name
= name_lookup (daemon
, arg_name
);
1136 client
= g_hash_table_lookup (daemon
->clients
, arg_name
);
1138 _g_freedesktop_dbus_complete_name_has_owner (object
, invocation
,
1139 name
!= NULL
|| client
!= NULL
);
1144 handle_release_name (_GFreedesktopDBus
*object
,
1145 GDBusMethodInvocation
*invocation
,
1146 const gchar
*arg_name
)
1148 Client
*client
= g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation
)), "client");
1149 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1153 if (!g_dbus_is_name (arg_name
))
1155 g_dbus_method_invocation_return_error (invocation
,
1156 G_DBUS_ERROR
, G_DBUS_ERROR_INVALID_ARGS
,
1157 "Given bus name \"%s\" is not valid", arg_name
);
1161 if (*arg_name
== ':')
1163 g_dbus_method_invocation_return_error (invocation
,
1164 G_DBUS_ERROR
, G_DBUS_ERROR_INVALID_ARGS
,
1165 "Cannot release a service starting with ':' such as \"%s\"", arg_name
);
1169 if (strcmp (arg_name
, DBUS_SERVICE_NAME
) == 0)
1171 g_dbus_method_invocation_return_error (invocation
,
1172 G_DBUS_ERROR
, G_DBUS_ERROR_INVALID_ARGS
,
1173 "Cannot release a service named " DBUS_SERVICE_NAME
", because that is owned by the bus");
1177 name
= name_lookup (daemon
, arg_name
);
1180 result
= DBUS_RELEASE_NAME_REPLY_NON_EXISTENT
;
1181 else if (name
->owner
&& name
->owner
->client
== client
)
1183 name_release_owner (name
);
1184 result
= DBUS_RELEASE_NAME_REPLY_RELEASED
;
1186 else if (name_unqueue_owner (name
, client
))
1187 result
= DBUS_RELEASE_NAME_REPLY_RELEASED
;
1189 result
= DBUS_RELEASE_NAME_REPLY_NOT_OWNER
;
1191 _g_freedesktop_dbus_complete_release_name (object
, invocation
, result
);
1196 handle_reload_config (_GFreedesktopDBus
*object
,
1197 GDBusMethodInvocation
*invocation
)
1199 _g_freedesktop_dbus_complete_reload_config (object
, invocation
);
1204 handle_update_activation_environment (_GFreedesktopDBus
*object
,
1205 GDBusMethodInvocation
*invocation
,
1206 GVariant
*arg_environment
)
1208 g_dbus_method_invocation_return_error (invocation
,
1209 G_DBUS_ERROR
, G_DBUS_ERROR_FAILED
,
1210 "UpdateActivationEnvironment not implemented");
1215 handle_remove_match (_GFreedesktopDBus
*object
,
1216 GDBusMethodInvocation
*invocation
,
1217 const gchar
*arg_rule
)
1219 Client
*client
= g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation
)), "client");
1220 Match
*match
, *other_match
;
1223 match
= match_new (arg_rule
);
1226 g_dbus_method_invocation_return_error (invocation
,
1227 G_DBUS_ERROR
, G_DBUS_ERROR_MATCH_RULE_INVALID
,
1228 "Invalid rule: %s", arg_rule
);
1231 for (l
= client
->matches
; l
!= NULL
; l
= l
->next
)
1233 other_match
= l
->data
;
1234 if (match_equal (match
, other_match
))
1236 match_free (other_match
);
1237 client
->matches
= g_list_delete_link (client
->matches
, l
);
1243 g_dbus_method_invocation_return_error (invocation
,
1244 G_DBUS_ERROR
, G_DBUS_ERROR_MATCH_RULE_NOT_FOUND
,
1245 "The given match rule wasn't found and can't be removed");
1247 _g_freedesktop_dbus_complete_remove_match (object
, invocation
);
1256 handle_request_name (_GFreedesktopDBus
*object
,
1257 GDBusMethodInvocation
*invocation
,
1258 const gchar
*arg_name
,
1261 Client
*client
= g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation
)), "client");
1262 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1267 if (!g_dbus_is_name (arg_name
))
1269 g_dbus_method_invocation_return_error (invocation
,
1270 G_DBUS_ERROR
, G_DBUS_ERROR_INVALID_ARGS
,
1271 "Requested bus name \"%s\" is not valid", arg_name
);
1275 if (*arg_name
== ':')
1277 g_dbus_method_invocation_return_error (invocation
,
1278 G_DBUS_ERROR
, G_DBUS_ERROR_INVALID_ARGS
,
1279 "Cannot acquire a service starting with ':' such as \"%s\"", arg_name
);
1283 if (strcmp (arg_name
, DBUS_SERVICE_NAME
) == 0)
1285 g_dbus_method_invocation_return_error (invocation
,
1286 G_DBUS_ERROR
, G_DBUS_ERROR_INVALID_ARGS
,
1287 "Cannot acquire a service named " DBUS_SERVICE_NAME
", because that is reserved");
1291 name
= name_ensure (daemon
, arg_name
);
1292 if (name
->owner
== NULL
)
1294 owner
= name_owner_new (client
, flags
);
1295 name_replace_owner (name
, owner
);
1297 result
= DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER
;
1299 else if (name
->owner
&& name
->owner
->client
== client
)
1301 name
->owner
->flags
= flags
;
1302 result
= DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER
;
1304 else if ((flags
& DBUS_NAME_FLAG_DO_NOT_QUEUE
) &&
1305 (!(flags
& DBUS_NAME_FLAG_REPLACE_EXISTING
) ||
1306 !(name
->owner
->flags
& DBUS_NAME_FLAG_ALLOW_REPLACEMENT
)))
1308 /* Unqueue if queued */
1309 name_unqueue_owner (name
, client
);
1310 result
= DBUS_REQUEST_NAME_REPLY_EXISTS
;
1312 else if (!(flags
& DBUS_NAME_FLAG_DO_NOT_QUEUE
) &&
1313 (!(flags
& DBUS_NAME_FLAG_REPLACE_EXISTING
) ||
1314 !(name
->owner
->flags
& DBUS_NAME_FLAG_ALLOW_REPLACEMENT
)))
1316 /* Queue the connection */
1317 owner
= name_owner_new (client
, flags
);
1318 name_queue_owner (name
, owner
);
1319 result
= DBUS_REQUEST_NAME_REPLY_IN_QUEUE
;
1323 /* Replace the current owner */
1325 owner
= name_owner_new (client
, flags
);
1326 name_replace_owner (name
, owner
);
1328 result
= DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER
;
1333 _g_freedesktop_dbus_complete_request_name (object
, invocation
, result
);
1338 handle_start_service_by_name (_GFreedesktopDBus
*object
,
1339 GDBusMethodInvocation
*invocation
,
1340 const gchar
*arg_name
,
1343 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1346 name
= name_lookup (daemon
, arg_name
);
1348 _g_freedesktop_dbus_complete_start_service_by_name (object
, invocation
,
1349 DBUS_START_REPLY_ALREADY_RUNNING
);
1351 g_dbus_method_invocation_return_error (invocation
,
1352 G_DBUS_ERROR
, G_DBUS_ERROR_SERVICE_UNKNOWN
,
1353 "No support for activation for name: %s", arg_name
);
1360 return_error (Client
*client
, GDBusMessage
*message
,
1363 const gchar
*format
,
1366 GDBusMessage
*reply
;
1368 char *error_message
;
1370 gchar
*dbus_error_name
;
1372 va_start (var_args
, format
);
1373 error_message
= g_strdup_vprintf (format
, var_args
);
1376 error
= g_error_new_literal (domain
, code
, "");
1377 dbus_error_name
= g_dbus_error_encode_gerror (error
);
1379 reply
= g_dbus_message_new_method_error_literal (message
,
1383 g_error_free (error
);
1384 g_free (dbus_error_name
);
1385 g_free (error_message
);
1387 if (!g_dbus_connection_send_message (client
->connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
))
1388 g_warning ("Error sending reply");
1389 g_object_unref (reply
);
1392 static GDBusMessage
*
1393 route_message (Client
*source_client
, GDBusMessage
*message
)
1396 Client
*dest_client
;
1397 GDBusDaemon
*daemon
;
1399 daemon
= source_client
->daemon
;
1402 dest
= g_dbus_message_get_destination (message
);
1403 if (dest
!= NULL
&& strcmp (dest
, DBUS_SERVICE_NAME
) != 0)
1405 dest_client
= g_hash_table_lookup (daemon
->clients
, dest
);
1407 if (dest_client
== NULL
)
1410 name
= name_lookup (daemon
, dest
);
1411 if (name
&& name
->owner
)
1412 dest_client
= name
->owner
->client
;
1415 if (dest_client
== NULL
)
1417 if (g_dbus_message_get_message_type (message
) == G_DBUS_MESSAGE_TYPE_METHOD_CALL
)
1418 return_error (source_client
, message
,
1419 G_DBUS_ERROR
, G_DBUS_ERROR_SERVICE_UNKNOWN
,
1420 "The name %s is unknown", dest
);
1424 GError
*error
= NULL
;
1426 if (!g_dbus_connection_send_message (dest_client
->connection
, message
, G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL
, NULL
, &error
))
1428 g_warning ("Error forwarding message: %s", error
->message
);
1429 g_error_free (error
);
1434 broadcast_message (daemon
, message
, dest_client
!= NULL
, TRUE
, dest_client
);
1436 /* Swallow messages not for the bus */
1437 if (dest
== NULL
|| strcmp (dest
, DBUS_SERVICE_NAME
) != 0)
1439 g_object_unref (message
);
1446 static GDBusMessage
*
1447 copy_if_locked (GDBusMessage
*message
)
1449 if (g_dbus_message_get_locked (message
))
1451 GDBusMessage
*copy
= g_dbus_message_copy (message
, NULL
);
1452 g_object_unref (message
);
1458 static GDBusMessage
*
1459 filter_function (GDBusConnection
*connection
,
1460 GDBusMessage
*message
,
1464 Client
*client
= user_data
;
1465 char *types
[] = {"invalid", "method_call", "method_return", "error", "signal" };
1468 g_printerr ("%s%s %s %d(%d) sender: %s destination: %s %s %s.%s\n",
1470 incoming
? "->" : "<-",
1471 types
[g_dbus_message_get_message_type (message
)],
1472 g_dbus_message_get_serial (message
),
1473 g_dbus_message_get_reply_serial (message
),
1474 g_dbus_message_get_sender (message
),
1475 g_dbus_message_get_destination (message
),
1476 g_dbus_message_get_path (message
),
1477 g_dbus_message_get_interface (message
),
1478 g_dbus_message_get_member (message
));
1482 /* Ensure its not locked so we can set the sender */
1483 message
= copy_if_locked (message
);
1484 if (message
== NULL
)
1486 g_warning ("Failed to copy incoming message");
1489 g_dbus_message_set_sender (message
, client
->id
);
1491 return route_message (client
, message
);
1495 if (g_dbus_message_get_sender (message
) == NULL
)
1497 message
= copy_if_locked (message
);
1498 g_dbus_message_set_sender (message
, DBUS_SERVICE_NAME
);
1500 if (g_dbus_message_get_destination (message
) == NULL
)
1502 message
= copy_if_locked (message
);
1503 g_dbus_message_set_destination (message
, client
->id
);
1511 on_new_connection (GDBusServer
*server
,
1512 GDBusConnection
*connection
,
1515 GDBusDaemon
*daemon
= user_data
;
1517 g_dbus_connection_set_exit_on_close (connection
, FALSE
);
1519 if (daemon
->timeout
)
1521 g_source_remove (daemon
->timeout
);
1522 daemon
->timeout
= 0;
1525 client_new (daemon
, connection
);
1531 on_authorize_authenticated_peer (GDBusAuthObserver
*observer
,
1533 GCredentials
*credentials
,
1536 gboolean authorized
= TRUE
;
1538 if (credentials
!= NULL
)
1540 GCredentials
*own_credentials
;
1542 own_credentials
= g_credentials_new ();
1543 authorized
= g_credentials_is_same_user (credentials
, own_credentials
, NULL
);
1544 g_object_unref (own_credentials
);
1551 g_dbus_daemon_finalize (GObject
*object
)
1553 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1556 if (daemon
->timeout
)
1557 g_source_remove (daemon
->timeout
);
1559 clients
= g_hash_table_get_values (daemon
->clients
);
1560 for (l
= clients
; l
!= NULL
; l
= l
->next
)
1561 client_free (l
->data
);
1562 g_list_free (clients
);
1564 g_assert (g_hash_table_size (daemon
->clients
) == 0);
1565 g_assert (g_hash_table_size (daemon
->names
) == 0);
1567 g_hash_table_destroy (daemon
->clients
);
1568 g_hash_table_destroy (daemon
->names
);
1570 g_object_unref (daemon
->server
);
1574 g_rmdir (daemon
->tmpdir
);
1575 g_free (daemon
->tmpdir
);
1578 g_free (daemon
->guid
);
1579 g_free (daemon
->address
);
1581 G_OBJECT_CLASS (g_dbus_daemon_parent_class
)->finalize (object
);
1585 g_dbus_daemon_init (GDBusDaemon
*daemon
)
1587 daemon
->next_major_id
= 1;
1588 daemon
->clients
= g_hash_table_new_full (g_str_hash
, g_str_equal
, NULL
, NULL
);
1589 daemon
->names
= g_hash_table_new_full (g_str_hash
, g_str_equal
, NULL
, NULL
);
1590 daemon
->guid
= g_dbus_generate_guid ();
1594 initable_init (GInitable
*initable
,
1595 GCancellable
*cancellable
,
1598 GDBusDaemon
*daemon
= G_DBUS_DAEMON (initable
);
1599 GDBusAuthObserver
*observer
;
1600 GDBusServerFlags flags
;
1602 flags
= G_DBUS_SERVER_FLAGS_NONE
;
1603 if (daemon
->address
== NULL
)
1606 if (g_unix_socket_address_abstract_names_supported ())
1607 daemon
->address
= g_strdup ("unix:tmpdir=/tmp/gdbus-daemon");
1610 daemon
->tmpdir
= g_dir_make_tmp ("gdbus-daemon-XXXXXX", NULL
);
1611 daemon
->address
= g_strdup_printf ("unix:tmpdir=%s", daemon
->tmpdir
);
1614 daemon
->address
= g_strdup ("nonce-tcp:");
1615 flags
|= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS
;
1619 observer
= g_dbus_auth_observer_new ();
1620 daemon
->server
= g_dbus_server_new_sync (daemon
->address
,
1626 if (daemon
->server
== NULL
)
1628 g_object_unref (observer
);
1633 g_dbus_server_start (daemon
->server
);
1635 g_signal_connect (daemon
->server
, "new-connection",
1636 G_CALLBACK (on_new_connection
),
1638 g_signal_connect (observer
,
1639 "authorize-authenticated-peer",
1640 G_CALLBACK (on_authorize_authenticated_peer
),
1643 g_object_unref (observer
);
1649 g_dbus_daemon_set_property (GObject
*object
,
1651 const GValue
*value
,
1654 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1659 g_free (daemon
->address
);
1660 daemon
->address
= g_value_dup_string (value
);
1664 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
1669 g_dbus_daemon_get_property (GObject
*object
,
1674 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1679 g_value_set_string (value
, daemon
->address
);
1683 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
1688 g_dbus_daemon_class_init (GDBusDaemonClass
*klass
)
1690 GObjectClass
*gobject_class
;
1692 gobject_class
= G_OBJECT_CLASS (klass
);
1693 gobject_class
->finalize
= g_dbus_daemon_finalize
;
1694 gobject_class
->set_property
= g_dbus_daemon_set_property
;
1695 gobject_class
->get_property
= g_dbus_daemon_get_property
;
1697 g_dbus_daemon_signals
[SIGNAL_IDLE_TIMEOUT
] =
1698 g_signal_new ("idle-timeout",
1703 g_cclosure_marshal_VOID__VOID
,
1706 g_object_class_install_property (gobject_class
,
1708 g_param_spec_string ("address",
1710 "The address the bus should use",
1713 G_PARAM_CONSTRUCT_ONLY
|
1714 G_PARAM_STATIC_STRINGS
));
1718 g_dbus_daemon_iface_init (_GFreedesktopDBusIface
*iface
)
1720 iface
->handle_add_match
= handle_add_match
;
1721 iface
->handle_get_connection_selinux_security_context
= handle_get_connection_selinux_security_context
;
1722 iface
->handle_get_connection_unix_process_id
= handle_get_connection_unix_process_id
;
1723 iface
->handle_get_connection_unix_user
= handle_get_connection_unix_user
;
1724 iface
->handle_get_id
= handle_get_id
;
1725 iface
->handle_get_name_owner
= handle_get_name_owner
;
1726 iface
->handle_hello
= handle_hello
;
1727 iface
->handle_list_activatable_names
= handle_list_activatable_names
;
1728 iface
->handle_list_names
= handle_list_names
;
1729 iface
->handle_list_queued_owners
= handle_list_queued_owners
;
1730 iface
->handle_name_has_owner
= handle_name_has_owner
;
1731 iface
->handle_release_name
= handle_release_name
;
1732 iface
->handle_reload_config
= handle_reload_config
;
1733 iface
->handle_update_activation_environment
= handle_update_activation_environment
;
1734 iface
->handle_remove_match
= handle_remove_match
;
1735 iface
->handle_request_name
= handle_request_name
;
1736 iface
->handle_start_service_by_name
= handle_start_service_by_name
;
1740 initable_iface_init (GInitableIface
*initable_iface
)
1742 initable_iface
->init
= initable_init
;
1746 _g_dbus_daemon_new (const char *address
,
1747 GCancellable
*cancellable
,
1750 return g_initable_new (G_TYPE_DBUS_DAEMON
,
1758 _g_dbus_daemon_get_address (GDBusDaemon
*daemon
)
1760 return g_dbus_server_get_client_address (daemon
->server
);