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
);
599 if (!(g_str_has_prefix (value
, element
->value
) &&
600 (value
[len
] == 0 || value
[len
] == '/')))
603 case CHECK_TYPE_PATH_RELATED
:
604 len
= strlen (element
->value
);
605 len2
= strlen (value
);
607 if (!(strcmp (value
, element
->value
) == 0 ||
608 (len2
> 0 && value
[len2
-1] == '/' && g_str_has_prefix (element
->value
, value
)) ||
609 (len
> 0 && element
->value
[len
-1] == '/' && g_str_has_prefix (value
, element
->value
))))
612 case CHECK_TYPE_NAMESPACE_PREFIX
:
613 len
= strlen (element
->value
);
614 if (!(g_str_has_prefix (value
, element
->value
) &&
615 (value
[len
] == 0 || value
[len
] == '.')))
619 g_assert_not_reached ();
627 broadcast_message (GDBusDaemon
*daemon
,
628 GDBusMessage
*message
,
629 gboolean has_destination
,
630 gboolean preserve_serial
,
633 GList
*clients
, *l
, *ll
;
636 clients
= g_hash_table_get_values (daemon
->clients
);
637 for (l
= clients
; l
!= NULL
; l
= l
->next
)
639 Client
*client
= l
->data
;
641 if (client
== not_to
)
644 for (ll
= client
->matches
; ll
!= NULL
; ll
= ll
->next
)
646 Match
*match
= ll
->data
;
648 if (match_matches (daemon
, match
, message
, has_destination
))
654 copy
= g_dbus_message_copy (message
, NULL
);
657 g_dbus_connection_send_message (client
->connection
, copy
,
658 preserve_serial
?G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL
:0, NULL
, NULL
);
659 g_object_unref (copy
);
664 g_list_free (clients
);
668 send_name_owner_changed (GDBusDaemon
*daemon
,
670 const char *old_owner
,
671 const char *new_owner
)
673 GDBusMessage
*signal_message
;
675 signal_message
= g_dbus_message_new_signal ("/org/freedesktop/DBus",
676 "org.freedesktop.DBus",
678 g_dbus_message_set_body (signal_message
,
679 g_variant_new ("(sss)",
681 old_owner
? old_owner
: "",
682 new_owner
? new_owner
: ""));
684 broadcast_message (daemon
, signal_message
, FALSE
, FALSE
, NULL
);
685 g_object_unref (signal_message
);
690 name_unqueue_owner (Name
*name
, Client
*client
)
694 for (l
= name
->queue
; l
!= NULL
; l
= l
->next
)
696 NameOwner
*other
= l
->data
;
698 if (other
->client
== client
)
700 name
->queue
= g_list_delete_link (name
->queue
, l
);
702 name_owner_free (other
);
711 name_replace_owner (Name
*name
, NameOwner
*owner
)
713 GDBusDaemon
*daemon
= name
->daemon
;
714 NameOwner
*old_owner
;
715 char *old_name
= NULL
, *new_name
= NULL
;
716 Client
*new_client
= NULL
;
719 new_client
= owner
->client
;
723 old_owner
= name
->owner
;
726 Client
*old_client
= old_owner
->client
;
728 g_assert (old_owner
->client
!= new_client
);
730 g_dbus_connection_emit_signal (old_client
->connection
,
731 NULL
, "/org/freedesktop/DBus",
732 "org.freedesktop.DBus", "NameLost",
733 g_variant_new ("(s)",
736 old_name
= g_strdup (old_client
->id
);
737 if (old_owner
->flags
& DBUS_NAME_FLAG_DO_NOT_QUEUE
)
740 name_owner_free (old_owner
);
743 name
->queue
= g_list_prepend (name
->queue
, old_owner
);
749 name_unqueue_owner (name
, owner
->client
);
751 new_name
= new_client
->id
;
753 g_dbus_connection_emit_signal (new_client
->connection
,
754 NULL
, "/org/freedesktop/DBus",
755 "org.freedesktop.DBus", "NameAcquired",
756 g_variant_new ("(s)",
760 send_name_owner_changed (daemon
, name
->name
, old_name
, new_name
);
768 name_release_owner (Name
*name
)
770 NameOwner
*next_owner
= NULL
;
774 /* Will someone else take over? */
777 next_owner
= name
->queue
->data
;
779 name
->queue
= g_list_delete_link (name
->queue
, name
->queue
);
782 name
->owner
->flags
|= DBUS_NAME_FLAG_DO_NOT_QUEUE
;
783 name_replace_owner (name
, next_owner
);
789 name_queue_owner (Name
*name
, NameOwner
*owner
)
793 for (l
= name
->queue
; l
!= NULL
; l
= l
->next
)
795 NameOwner
*other
= l
->data
;
797 if (other
->client
== owner
->client
)
799 other
->flags
= owner
->flags
;
800 name_owner_free (owner
);
805 name
->queue
= g_list_append (name
->queue
, owner
);
810 client_new (GDBusDaemon
*daemon
, GDBusConnection
*connection
)
813 GError
*error
= NULL
;
815 client
= g_new0 (Client
, 1);
816 client
->daemon
= daemon
;
817 client
->id
= g_strdup_printf (":%d.%d", daemon
->next_major_id
, daemon
->next_minor_id
);
818 client
->connection
= g_object_ref (connection
);
820 if (daemon
->next_minor_id
== G_MAXUINT32
)
822 daemon
->next_minor_id
= 0;
823 daemon
->next_major_id
++;
826 daemon
->next_minor_id
++;
828 g_object_set_data (G_OBJECT (connection
), "client", client
);
829 g_hash_table_insert (daemon
->clients
, client
->id
, client
);
831 g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (daemon
), connection
,
832 "/org/freedesktop/DBus", &error
);
833 g_assert_no_error (error
);
835 g_signal_connect (connection
, "closed", G_CALLBACK (connection_closed
), client
);
836 g_dbus_connection_add_filter (connection
,
840 send_name_owner_changed (daemon
, client
->id
, NULL
, client
->id
);
846 client_free (Client
*client
)
848 GDBusDaemon
*daemon
= client
->daemon
;
851 g_dbus_interface_skeleton_unexport_from_connection (G_DBUS_INTERFACE_SKELETON (daemon
),
854 g_hash_table_remove (daemon
->clients
, client
->id
);
856 names
= g_hash_table_get_values (daemon
->names
);
857 for (l
= names
; l
!= NULL
; l
= l
->next
)
859 Name
*name
= l
->data
;
863 if (name
->owner
&& name
->owner
->client
== client
)
864 name_release_owner (name
);
866 name_unqueue_owner (name
, client
);
872 send_name_owner_changed (daemon
, client
->id
, client
->id
, NULL
);
874 g_object_unref (client
->connection
);
876 for (l
= client
->matches
; l
!= NULL
; l
= l
->next
)
877 match_free (l
->data
);
878 g_list_free (client
->matches
);
885 idle_timeout_cb (gpointer user_data
)
887 GDBusDaemon
*daemon
= user_data
;
891 g_signal_emit (daemon
,
892 g_dbus_daemon_signals
[SIGNAL_IDLE_TIMEOUT
],
895 return G_SOURCE_REMOVE
;
899 connection_closed (GDBusConnection
*connection
,
900 gboolean remote_peer_vanished
,
904 GDBusDaemon
*daemon
= client
->daemon
;
906 client_free (client
);
908 if (g_hash_table_size (daemon
->clients
) == 0)
909 daemon
->timeout
= g_timeout_add (IDLE_TIMEOUT_MSEC
,
915 handle_add_match (_GFreedesktopDBus
*object
,
916 GDBusMethodInvocation
*invocation
,
917 const gchar
*arg_rule
)
919 Client
*client
= g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation
)), "client");
922 match
= match_new (arg_rule
);
925 g_dbus_method_invocation_return_error (invocation
,
926 G_DBUS_ERROR
, G_DBUS_ERROR_MATCH_RULE_INVALID
,
927 "Invalid rule: %s", arg_rule
);
930 client
->matches
= g_list_prepend (client
->matches
, match
);
931 _g_freedesktop_dbus_complete_add_match (object
, invocation
);
937 handle_get_connection_selinux_security_context (_GFreedesktopDBus
*object
,
938 GDBusMethodInvocation
*invocation
,
939 const gchar
*arg_name
)
941 g_dbus_method_invocation_return_error (invocation
,
942 G_DBUS_ERROR
, G_DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN
,
943 "selinux context not supported");
944 _g_freedesktop_dbus_complete_get_connection_selinux_security_context (object
, invocation
, "");
949 handle_get_connection_unix_process_id (_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_UNIX_PROCESS_ID_UNKNOWN
,
955 "connection pid not supported");
960 handle_get_connection_unix_user (_GFreedesktopDBus
*object
,
961 GDBusMethodInvocation
*invocation
,
962 const gchar
*arg_name
)
964 g_dbus_method_invocation_return_error (invocation
,
965 G_DBUS_ERROR
, G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN
,
966 "connection user not supported");
971 handle_get_id (_GFreedesktopDBus
*object
,
972 GDBusMethodInvocation
*invocation
)
974 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
975 _g_freedesktop_dbus_complete_get_id (object
, invocation
,
981 handle_get_name_owner (_GFreedesktopDBus
*object
,
982 GDBusMethodInvocation
*invocation
,
983 const gchar
*arg_name
)
985 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
988 if (strcmp (arg_name
, DBUS_SERVICE_NAME
) == 0)
990 _g_freedesktop_dbus_complete_get_name_owner (object
, invocation
, DBUS_SERVICE_NAME
);
994 if (arg_name
[0] == ':')
996 if (g_hash_table_lookup (daemon
->clients
, arg_name
) == NULL
)
997 g_dbus_method_invocation_return_error (invocation
,
998 G_DBUS_ERROR
, G_DBUS_ERROR_NAME_HAS_NO_OWNER
,
999 "Could not get owner of name '%s': no such name", arg_name
);
1001 _g_freedesktop_dbus_complete_get_name_owner (object
, invocation
, arg_name
);
1005 name
= name_lookup (daemon
, arg_name
);
1006 if (name
== NULL
|| name
->owner
== NULL
)
1008 g_dbus_method_invocation_return_error (invocation
,
1009 G_DBUS_ERROR
, G_DBUS_ERROR_NAME_HAS_NO_OWNER
,
1010 "Could not get owner of name '%s': no such name", arg_name
);
1014 _g_freedesktop_dbus_complete_get_name_owner (object
, invocation
, name
->owner
->client
->id
);
1019 handle_hello (_GFreedesktopDBus
*object
,
1020 GDBusMethodInvocation
*invocation
)
1022 Client
*client
= g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation
)), "client");
1023 _g_freedesktop_dbus_complete_hello (object
, invocation
, client
->id
);
1025 g_dbus_connection_emit_signal (client
->connection
,
1026 NULL
, "/org/freedesktop/DBus",
1027 "org.freedesktop.DBus", "NameAcquired",
1028 g_variant_new ("(s)",
1035 handle_list_activatable_names (_GFreedesktopDBus
*object
,
1036 GDBusMethodInvocation
*invocation
)
1038 const char *names
[] = { NULL
};
1040 _g_freedesktop_dbus_complete_list_activatable_names (object
,
1047 handle_list_names (_GFreedesktopDBus
*object
,
1048 GDBusMethodInvocation
*invocation
)
1050 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1052 GList
*clients
, *names
, *l
;
1054 array
= g_ptr_array_new ();
1056 clients
= g_hash_table_get_values (daemon
->clients
);
1057 for (l
= clients
; l
!= NULL
; l
= l
->next
)
1059 Client
*client
= l
->data
;
1061 g_ptr_array_add (array
, client
->id
);
1064 g_list_free (clients
);
1066 names
= g_hash_table_get_values (daemon
->names
);
1067 for (l
= names
; l
!= NULL
; l
= l
->next
)
1069 Name
*name
= l
->data
;
1071 g_ptr_array_add (array
, name
->name
);
1074 g_list_free (names
);
1076 g_ptr_array_add (array
, NULL
);
1078 _g_freedesktop_dbus_complete_list_names (object
,
1080 (const gchar
* const*)array
->pdata
);
1081 g_ptr_array_free (array
, TRUE
);
1086 handle_list_queued_owners (_GFreedesktopDBus
*object
,
1087 GDBusMethodInvocation
*invocation
,
1088 const gchar
*arg_name
)
1090 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1095 array
= g_ptr_array_new ();
1097 name
= name_lookup (daemon
, arg_name
);
1098 if (name
&& name
->owner
)
1100 for (l
= name
->queue
; l
!= NULL
; l
= l
->next
)
1102 Client
*client
= l
->data
;
1104 g_ptr_array_add (array
, client
->id
);
1108 g_ptr_array_add (array
, NULL
);
1110 _g_freedesktop_dbus_complete_list_queued_owners (object
,
1112 (const gchar
* const*)array
->pdata
);
1113 g_ptr_array_free (array
, TRUE
);
1118 handle_name_has_owner (_GFreedesktopDBus
*object
,
1119 GDBusMethodInvocation
*invocation
,
1120 const gchar
*arg_name
)
1122 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1126 name
= name_lookup (daemon
, arg_name
);
1127 client
= g_hash_table_lookup (daemon
->clients
, arg_name
);
1129 _g_freedesktop_dbus_complete_name_has_owner (object
, invocation
,
1130 name
!= NULL
|| client
!= NULL
);
1135 handle_release_name (_GFreedesktopDBus
*object
,
1136 GDBusMethodInvocation
*invocation
,
1137 const gchar
*arg_name
)
1139 Client
*client
= g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation
)), "client");
1140 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1144 if (!g_dbus_is_name (arg_name
))
1146 g_dbus_method_invocation_return_error (invocation
,
1147 G_DBUS_ERROR
, G_DBUS_ERROR_INVALID_ARGS
,
1148 "Given bus name \"%s\" is not valid", arg_name
);
1152 if (*arg_name
== ':')
1154 g_dbus_method_invocation_return_error (invocation
,
1155 G_DBUS_ERROR
, G_DBUS_ERROR_INVALID_ARGS
,
1156 "Cannot release a service starting with ':' such as \"%s\"", arg_name
);
1160 if (strcmp (arg_name
, DBUS_SERVICE_NAME
) == 0)
1162 g_dbus_method_invocation_return_error (invocation
,
1163 G_DBUS_ERROR
, G_DBUS_ERROR_INVALID_ARGS
,
1164 "Cannot release a service named " DBUS_SERVICE_NAME
", because that is owned by the bus");
1168 name
= name_lookup (daemon
, arg_name
);
1171 result
= DBUS_RELEASE_NAME_REPLY_NON_EXISTENT
;
1172 else if (name
->owner
&& name
->owner
->client
== client
)
1174 name_release_owner (name
);
1175 result
= DBUS_RELEASE_NAME_REPLY_RELEASED
;
1177 else if (name_unqueue_owner (name
, client
))
1178 result
= DBUS_RELEASE_NAME_REPLY_RELEASED
;
1180 result
= DBUS_RELEASE_NAME_REPLY_NOT_OWNER
;
1182 _g_freedesktop_dbus_complete_release_name (object
, invocation
, result
);
1187 handle_reload_config (_GFreedesktopDBus
*object
,
1188 GDBusMethodInvocation
*invocation
)
1190 _g_freedesktop_dbus_complete_reload_config (object
, invocation
);
1195 handle_update_activation_environment (_GFreedesktopDBus
*object
,
1196 GDBusMethodInvocation
*invocation
,
1197 GVariant
*arg_environment
)
1199 g_dbus_method_invocation_return_error (invocation
,
1200 G_DBUS_ERROR
, G_DBUS_ERROR_FAILED
,
1201 "UpdateActivationEnvironment not implemented");
1206 handle_remove_match (_GFreedesktopDBus
*object
,
1207 GDBusMethodInvocation
*invocation
,
1208 const gchar
*arg_rule
)
1210 Client
*client
= g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation
)), "client");
1211 Match
*match
, *other_match
;
1214 match
= match_new (arg_rule
);
1217 g_dbus_method_invocation_return_error (invocation
,
1218 G_DBUS_ERROR
, G_DBUS_ERROR_MATCH_RULE_INVALID
,
1219 "Invalid rule: %s", arg_rule
);
1222 for (l
= client
->matches
; l
!= NULL
; l
= l
->next
)
1224 other_match
= l
->data
;
1225 if (match_equal (match
, other_match
))
1227 match_free (other_match
);
1228 client
->matches
= g_list_delete_link (client
->matches
, l
);
1234 g_dbus_method_invocation_return_error (invocation
,
1235 G_DBUS_ERROR
, G_DBUS_ERROR_MATCH_RULE_NOT_FOUND
,
1236 "The given match rule wasn't found and can't be removed");
1238 _g_freedesktop_dbus_complete_remove_match (object
, invocation
);
1247 handle_request_name (_GFreedesktopDBus
*object
,
1248 GDBusMethodInvocation
*invocation
,
1249 const gchar
*arg_name
,
1252 Client
*client
= g_object_get_data (G_OBJECT (g_dbus_method_invocation_get_connection (invocation
)), "client");
1253 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1258 if (!g_dbus_is_name (arg_name
))
1260 g_dbus_method_invocation_return_error (invocation
,
1261 G_DBUS_ERROR
, G_DBUS_ERROR_INVALID_ARGS
,
1262 "Requested bus name \"%s\" is not valid", arg_name
);
1266 if (*arg_name
== ':')
1268 g_dbus_method_invocation_return_error (invocation
,
1269 G_DBUS_ERROR
, G_DBUS_ERROR_INVALID_ARGS
,
1270 "Cannot acquire a service starting with ':' such as \"%s\"", arg_name
);
1274 if (strcmp (arg_name
, DBUS_SERVICE_NAME
) == 0)
1276 g_dbus_method_invocation_return_error (invocation
,
1277 G_DBUS_ERROR
, G_DBUS_ERROR_INVALID_ARGS
,
1278 "Cannot acquire a service named " DBUS_SERVICE_NAME
", because that is reserved");
1282 name
= name_ensure (daemon
, arg_name
);
1283 if (name
->owner
== NULL
)
1285 owner
= name_owner_new (client
, flags
);
1286 name_replace_owner (name
, owner
);
1288 result
= DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER
;
1290 else if (name
->owner
&& name
->owner
->client
== client
)
1292 name
->owner
->flags
= flags
;
1293 result
= DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER
;
1295 else if ((flags
& DBUS_NAME_FLAG_DO_NOT_QUEUE
) &&
1296 (!(flags
& DBUS_NAME_FLAG_REPLACE_EXISTING
) ||
1297 !(name
->owner
->flags
& DBUS_NAME_FLAG_ALLOW_REPLACEMENT
)))
1299 /* Unqueue if queued */
1300 name_unqueue_owner (name
, client
);
1301 result
= DBUS_REQUEST_NAME_REPLY_EXISTS
;
1303 else if (!(flags
& DBUS_NAME_FLAG_DO_NOT_QUEUE
) &&
1304 (!(flags
& DBUS_NAME_FLAG_REPLACE_EXISTING
) ||
1305 !(name
->owner
->flags
& DBUS_NAME_FLAG_ALLOW_REPLACEMENT
)))
1307 /* Queue the connection */
1308 owner
= name_owner_new (client
, flags
);
1309 name_queue_owner (name
, owner
);
1310 result
= DBUS_REQUEST_NAME_REPLY_IN_QUEUE
;
1314 /* Replace the current owner */
1316 owner
= name_owner_new (client
, flags
);
1317 name_replace_owner (name
, owner
);
1319 result
= DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER
;
1324 _g_freedesktop_dbus_complete_request_name (object
, invocation
, result
);
1329 handle_start_service_by_name (_GFreedesktopDBus
*object
,
1330 GDBusMethodInvocation
*invocation
,
1331 const gchar
*arg_name
,
1334 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1337 name
= name_lookup (daemon
, arg_name
);
1339 _g_freedesktop_dbus_complete_start_service_by_name (object
, invocation
,
1340 DBUS_START_REPLY_ALREADY_RUNNING
);
1342 g_dbus_method_invocation_return_error (invocation
,
1343 G_DBUS_ERROR
, G_DBUS_ERROR_SERVICE_UNKNOWN
,
1344 "No support for activation for name: %s", arg_name
);
1350 return_error (Client
*client
, GDBusMessage
*message
,
1353 const gchar
*format
,
1356 GDBusMessage
*reply
;
1358 char *error_message
;
1360 gchar
*dbus_error_name
;
1362 va_start (var_args
, format
);
1363 error_message
= g_strdup_vprintf (format
, var_args
);
1366 error
= g_error_new_literal (domain
, code
, "");
1367 dbus_error_name
= g_dbus_error_encode_gerror (error
);
1369 reply
= g_dbus_message_new_method_error_literal (message
,
1373 g_error_free (error
);
1374 g_free (dbus_error_name
);
1375 g_free (error_message
);
1377 if (!g_dbus_connection_send_message (client
->connection
, reply
, G_DBUS_SEND_MESSAGE_FLAGS_NONE
, NULL
, NULL
))
1378 g_warning ("Error sending reply");
1379 g_object_unref (reply
);
1382 static GDBusMessage
*
1383 route_message (Client
*source_client
, GDBusMessage
*message
)
1386 Client
*dest_client
;
1387 GDBusDaemon
*daemon
;
1389 daemon
= source_client
->daemon
;
1392 dest
= g_dbus_message_get_destination (message
);
1393 if (dest
!= NULL
&& strcmp (dest
, DBUS_SERVICE_NAME
) != 0)
1395 dest_client
= g_hash_table_lookup (daemon
->clients
, dest
);
1397 if (dest_client
== NULL
)
1400 name
= name_lookup (daemon
, dest
);
1401 if (name
&& name
->owner
)
1402 dest_client
= name
->owner
->client
;
1405 if (dest_client
== NULL
)
1407 if (g_dbus_message_get_message_type (message
) == G_DBUS_MESSAGE_TYPE_METHOD_CALL
)
1408 return_error (source_client
, message
,
1409 G_DBUS_ERROR
, G_DBUS_ERROR_SERVICE_UNKNOWN
,
1410 "The name %s is unknown", dest
);
1414 GError
*error
= NULL
;
1416 if (!g_dbus_connection_send_message (dest_client
->connection
, message
, G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL
, NULL
, &error
))
1418 g_warning ("Error forwarding message: %s", error
->message
);
1419 g_error_free (error
);
1424 broadcast_message (daemon
, message
, dest_client
!= NULL
, TRUE
, dest_client
);
1426 /* Swallow messages not for the bus */
1427 if (dest
== NULL
|| strcmp (dest
, DBUS_SERVICE_NAME
) != 0)
1429 g_object_unref (message
);
1436 static GDBusMessage
*
1437 copy_if_locked (GDBusMessage
*message
)
1439 if (g_dbus_message_get_locked (message
))
1441 GDBusMessage
*copy
= g_dbus_message_copy (message
, NULL
);
1442 g_object_unref (message
);
1448 static GDBusMessage
*
1449 filter_function (GDBusConnection
*connection
,
1450 GDBusMessage
*message
,
1454 Client
*client
= user_data
;
1455 char *types
[] = {"invalid", "method_call", "method_return", "error", "signal" };
1458 g_printerr ("%s%s %s %d(%d) sender: %s destination: %s %s %s.%s\n",
1460 incoming
? "->" : "<-",
1461 types
[g_dbus_message_get_message_type (message
)],
1462 g_dbus_message_get_serial (message
),
1463 g_dbus_message_get_reply_serial (message
),
1464 g_dbus_message_get_sender (message
),
1465 g_dbus_message_get_destination (message
),
1466 g_dbus_message_get_path (message
),
1467 g_dbus_message_get_interface (message
),
1468 g_dbus_message_get_member (message
));
1472 /* Ensure its not locked so we can set the sender */
1473 message
= copy_if_locked (message
);
1474 if (message
== NULL
)
1476 g_warning ("Failed to copy incoming message");
1479 g_dbus_message_set_sender (message
, client
->id
);
1481 return route_message (client
, message
);
1485 if (g_dbus_message_get_sender (message
) == NULL
)
1487 message
= copy_if_locked (message
);
1488 g_dbus_message_set_sender (message
, DBUS_SERVICE_NAME
);
1490 if (g_dbus_message_get_destination (message
) == NULL
)
1492 message
= copy_if_locked (message
);
1493 g_dbus_message_set_destination (message
, client
->id
);
1501 on_new_connection (GDBusServer
*server
,
1502 GDBusConnection
*connection
,
1505 GDBusDaemon
*daemon
= user_data
;
1507 g_dbus_connection_set_exit_on_close (connection
, FALSE
);
1509 if (daemon
->timeout
)
1511 g_source_remove (daemon
->timeout
);
1512 daemon
->timeout
= 0;
1515 client_new (daemon
, connection
);
1521 on_authorize_authenticated_peer (GDBusAuthObserver
*observer
,
1523 GCredentials
*credentials
,
1526 gboolean authorized
= TRUE
;
1528 if (credentials
!= NULL
)
1530 GCredentials
*own_credentials
;
1532 own_credentials
= g_credentials_new ();
1533 authorized
= g_credentials_is_same_user (credentials
, own_credentials
, NULL
);
1534 g_object_unref (own_credentials
);
1541 g_dbus_daemon_finalize (GObject
*object
)
1543 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1546 if (daemon
->timeout
)
1547 g_source_remove (daemon
->timeout
);
1549 clients
= g_hash_table_get_values (daemon
->clients
);
1550 for (l
= clients
; l
!= NULL
; l
= l
->next
)
1551 client_free (l
->data
);
1552 g_list_free (clients
);
1554 g_assert (g_hash_table_size (daemon
->clients
) == 0);
1555 g_assert (g_hash_table_size (daemon
->names
) == 0);
1557 g_hash_table_destroy (daemon
->clients
);
1558 g_hash_table_destroy (daemon
->names
);
1560 g_object_unref (daemon
->server
);
1564 g_rmdir (daemon
->tmpdir
);
1565 g_free (daemon
->tmpdir
);
1568 g_free (daemon
->guid
);
1569 g_free (daemon
->address
);
1571 G_OBJECT_CLASS (g_dbus_daemon_parent_class
)->finalize (object
);
1575 g_dbus_daemon_init (GDBusDaemon
*daemon
)
1577 daemon
->next_major_id
= 1;
1578 daemon
->clients
= g_hash_table_new_full (g_str_hash
, g_str_equal
, NULL
, NULL
);
1579 daemon
->names
= g_hash_table_new_full (g_str_hash
, g_str_equal
, NULL
, NULL
);
1580 daemon
->guid
= g_dbus_generate_guid ();
1584 initable_init (GInitable
*initable
,
1585 GCancellable
*cancellable
,
1588 GDBusDaemon
*daemon
= G_DBUS_DAEMON (initable
);
1589 GDBusAuthObserver
*observer
;
1590 GDBusServerFlags flags
;
1592 flags
= G_DBUS_SERVER_FLAGS_NONE
;
1593 if (daemon
->address
== NULL
)
1596 if (g_unix_socket_address_abstract_names_supported ())
1597 daemon
->address
= g_strdup ("unix:tmpdir=/tmp/gdbus-daemon");
1600 daemon
->tmpdir
= g_dir_make_tmp ("gdbus-daemon-XXXXXX", NULL
);
1601 daemon
->address
= g_strdup_printf ("unix:tmpdir=%s", daemon
->tmpdir
);
1604 daemon
->address
= g_strdup ("nonce-tcp:");
1605 flags
|= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS
;
1609 observer
= g_dbus_auth_observer_new ();
1610 daemon
->server
= g_dbus_server_new_sync (daemon
->address
,
1616 if (daemon
->server
== NULL
)
1618 g_object_unref (observer
);
1623 g_dbus_server_start (daemon
->server
);
1625 g_signal_connect (daemon
->server
, "new-connection",
1626 G_CALLBACK (on_new_connection
),
1628 g_signal_connect (observer
,
1629 "authorize-authenticated-peer",
1630 G_CALLBACK (on_authorize_authenticated_peer
),
1633 g_object_unref (observer
);
1639 g_dbus_daemon_set_property (GObject
*object
,
1641 const GValue
*value
,
1644 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1649 g_free (daemon
->address
);
1650 daemon
->address
= g_value_dup_string (value
);
1654 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
1659 g_dbus_daemon_get_property (GObject
*object
,
1664 GDBusDaemon
*daemon
= G_DBUS_DAEMON (object
);
1669 g_value_set_string (value
, daemon
->address
);
1673 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
1678 g_dbus_daemon_class_init (GDBusDaemonClass
*klass
)
1680 GObjectClass
*gobject_class
;
1682 gobject_class
= G_OBJECT_CLASS (klass
);
1683 gobject_class
->finalize
= g_dbus_daemon_finalize
;
1684 gobject_class
->set_property
= g_dbus_daemon_set_property
;
1685 gobject_class
->get_property
= g_dbus_daemon_get_property
;
1687 g_dbus_daemon_signals
[SIGNAL_IDLE_TIMEOUT
] =
1688 g_signal_new ("idle-timeout",
1693 g_cclosure_marshal_VOID__VOID
,
1696 g_object_class_install_property (gobject_class
,
1698 g_param_spec_string ("address",
1700 "The address the bus should use",
1703 G_PARAM_CONSTRUCT_ONLY
|
1704 G_PARAM_STATIC_STRINGS
));
1708 g_dbus_daemon_iface_init (_GFreedesktopDBusIface
*iface
)
1710 iface
->handle_add_match
= handle_add_match
;
1711 iface
->handle_get_connection_selinux_security_context
= handle_get_connection_selinux_security_context
;
1712 iface
->handle_get_connection_unix_process_id
= handle_get_connection_unix_process_id
;
1713 iface
->handle_get_connection_unix_user
= handle_get_connection_unix_user
;
1714 iface
->handle_get_id
= handle_get_id
;
1715 iface
->handle_get_name_owner
= handle_get_name_owner
;
1716 iface
->handle_hello
= handle_hello
;
1717 iface
->handle_list_activatable_names
= handle_list_activatable_names
;
1718 iface
->handle_list_names
= handle_list_names
;
1719 iface
->handle_list_queued_owners
= handle_list_queued_owners
;
1720 iface
->handle_name_has_owner
= handle_name_has_owner
;
1721 iface
->handle_release_name
= handle_release_name
;
1722 iface
->handle_reload_config
= handle_reload_config
;
1723 iface
->handle_update_activation_environment
= handle_update_activation_environment
;
1724 iface
->handle_remove_match
= handle_remove_match
;
1725 iface
->handle_request_name
= handle_request_name
;
1726 iface
->handle_start_service_by_name
= handle_start_service_by_name
;
1730 initable_iface_init (GInitableIface
*initable_iface
)
1732 initable_iface
->init
= initable_init
;
1736 _g_dbus_daemon_new (const char *address
,
1737 GCancellable
*cancellable
,
1740 return g_initable_new (G_TYPE_DBUS_DAEMON
,
1748 _g_dbus_daemon_get_address (GDBusDaemon
*daemon
)
1750 return g_dbus_server_get_client_address (daemon
->server
);