1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* services.c Service management
4 * Copyright (C) 2003 Red Hat, Inc.
5 * Copyright (C) 2003 CodeFactory AB
6 * Copyright (C) 2013 Samsung Electronics
8 * Licensed under the Academic Free License version 2.1
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include <dbus/dbus-hash.h>
28 #include <dbus/dbus-list.h>
29 #include <dbus/dbus-mempool.h>
30 #include <dbus/dbus-marshal-validate.h>
33 #include "connection.h"
35 #include "activation.h"
40 #ifdef ENABLE_KDBUS_TRANSPORT
41 #include <linux/types.h>
48 #include "dbus/kdbus.h"
55 BusRegistry *registry;
67 unsigned int allow_replacement : 1;
68 unsigned int do_not_queue : 1;
69 #ifdef ENABLE_KDBUS_TRANSPORT
70 unsigned int is_kdbus_starter : 1;
80 DBusHashTable *service_hash;
81 DBusMemPool *service_pool;
82 DBusMemPool *owner_pool;
84 DBusHashTable *service_sid_table;
88 bus_registry_new (BusContext *context)
90 BusRegistry *registry;
92 registry = dbus_new0 (BusRegistry, 1);
96 registry->refcount = 1;
97 registry->context = context;
99 registry->service_hash = _dbus_hash_table_new (DBUS_HASH_STRING,
101 if (registry->service_hash == NULL)
104 registry->service_pool = _dbus_mem_pool_new (sizeof (BusService),
107 if (registry->service_pool == NULL)
110 registry->owner_pool = _dbus_mem_pool_new (sizeof (BusOwner),
113 if (registry->owner_pool == NULL)
116 registry->service_sid_table = NULL;
121 bus_registry_unref (registry);
126 bus_registry_ref (BusRegistry *registry)
128 _dbus_assert (registry->refcount > 0);
129 registry->refcount += 1;
135 bus_registry_unref (BusRegistry *registry)
137 _dbus_assert (registry->refcount > 0);
138 registry->refcount -= 1;
140 if (registry->refcount == 0)
142 if (registry->service_hash)
143 _dbus_hash_table_unref (registry->service_hash);
144 if (registry->service_pool)
145 _dbus_mem_pool_free (registry->service_pool);
146 if (registry->owner_pool)
147 _dbus_mem_pool_free (registry->owner_pool);
148 if (registry->service_sid_table)
149 _dbus_hash_table_unref (registry->service_sid_table);
151 dbus_free (registry);
156 bus_registry_lookup (BusRegistry *registry,
157 const DBusString *service_name)
161 service = _dbus_hash_table_lookup_string (registry->service_hash,
162 _dbus_string_get_const_data (service_name));
168 _bus_service_find_owner_link (BusService *service,
169 DBusConnection *connection)
173 link = _dbus_list_get_first_link (&service->owners);
179 bus_owner = (BusOwner *) link->data;
180 if (bus_owner->conn == connection)
183 link = _dbus_list_get_next_link (&service->owners, link);
189 #ifdef ENABLE_KDBUS_TRANSPORT
190 static DBusConnection *
191 _bus_service_find_owner_connection (BusService *service,
192 const char* unique_name)
196 link = _dbus_list_get_first_link (&service->owners);
202 bus_owner = (BusOwner *) link->data;
203 if(!strcmp(bus_connection_get_name(bus_owner->conn), unique_name))
204 return bus_owner->conn;
206 link = _dbus_list_get_next_link (&service->owners, link);
214 bus_owner_set_flags (BusOwner *owner,
217 owner->allow_replacement =
218 (flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT) != FALSE;
220 owner->do_not_queue =
221 (flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) != FALSE;
223 #ifdef ENABLE_KDBUS_TRANSPORT
224 owner->is_kdbus_starter =
225 (flags & KDBUS_NAME_STARTER) != FALSE;
230 bus_owner_new (BusService *service,
231 DBusConnection *conn,
236 result = _dbus_mem_pool_alloc (service->registry->owner_pool);
239 result->refcount = 1;
240 /* don't ref the connection because we don't want
241 to block the connection from going away.
242 transactions take care of reffing the connection
243 but we need to use refcounting on the owner
244 so that the owner does not get freed before
245 we can deref the connection in the transaction
248 result->service = service;
250 if (!bus_connection_add_owned_service (conn, service))
252 _dbus_mem_pool_dealloc (service->registry->owner_pool, result);
256 bus_owner_set_flags (result, flags);
262 bus_owner_ref (BusOwner *owner)
264 _dbus_assert (owner->refcount > 0);
265 owner->refcount += 1;
271 bus_owner_unref (BusOwner *owner)
273 _dbus_assert (owner->refcount > 0);
274 owner->refcount -= 1;
276 if (owner->refcount == 0)
278 bus_connection_remove_owned_service (owner->conn, owner->service);
279 _dbus_mem_pool_dealloc (owner->service->registry->owner_pool, owner);
284 bus_registry_ensure (BusRegistry *registry,
285 const DBusString *service_name,
286 DBusConnection *owner_connection_if_created,
288 BusTransaction *transaction,
293 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
295 _dbus_assert (owner_connection_if_created != NULL);
296 _dbus_assert (transaction != NULL);
298 service = _dbus_hash_table_lookup_string (registry->service_hash,
299 _dbus_string_get_const_data (service_name));
303 service = _dbus_mem_pool_alloc (registry->service_pool);
310 service->registry = registry;
311 service->refcount = 1;
313 _dbus_verbose ("copying string %p '%s' to service->name\n",
314 service_name, _dbus_string_get_const_data (service_name));
315 if (!_dbus_string_copy_data (service_name, &service->name))
317 _dbus_mem_pool_dealloc (registry->service_pool, service);
321 _dbus_verbose ("copied string %p '%s' to '%s'\n",
322 service_name, _dbus_string_get_const_data (service_name),
325 if (!bus_driver_send_service_owner_changed (service->name,
327 bus_connection_get_name (owner_connection_if_created),
330 bus_service_unref (service);
334 if (!bus_activation_service_created (bus_context_get_activation (registry->context),
335 service->name, transaction, error))
337 bus_service_unref (service);
341 if (!bus_service_add_owner (service, owner_connection_if_created, flags,
344 bus_service_unref (service);
348 if (!_dbus_hash_table_insert_string (registry->service_hash,
352 /* The add_owner gets reverted on transaction cancel */
361 bus_registry_foreach (BusRegistry *registry,
362 BusServiceForeachFunction function,
367 _dbus_hash_iter_init (registry->service_hash, &iter);
368 while (_dbus_hash_iter_next (&iter))
370 BusService *service = _dbus_hash_iter_get_value (&iter);
372 (* function) (service, data);
377 bus_registry_list_services (BusRegistry *registry,
385 len = _dbus_hash_table_get_n_entries (registry->service_hash);
386 retval = dbus_new (char *, len + 1);
391 _dbus_hash_iter_init (registry->service_hash, &iter);
393 while (_dbus_hash_iter_next (&iter))
395 BusService *service = _dbus_hash_iter_get_value (&iter);
397 retval[i] = _dbus_strdup (service->name);
398 if (retval[i] == NULL)
413 for (j = 0; j < i; j++)
414 dbus_free (retval[j]);
421 bus_registry_acquire_service (BusRegistry *registry,
422 DBusConnection *connection,
423 const DBusString *service_name,
425 dbus_uint32_t *result,
426 BusTransaction *transaction,
430 DBusConnection *old_owner_conn;
431 BusClientPolicy *policy;
433 BusActivation *activation;
435 BusOwner *primary_owner;
439 if (!_dbus_validate_bus_name (service_name, 0,
440 _dbus_string_get_length (service_name)))
442 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
443 "Requested bus name \"%s\" is not valid",
444 _dbus_string_get_const_data (service_name));
446 _dbus_verbose ("Attempt to acquire invalid service name\n");
451 if (_dbus_string_get_byte (service_name, 0) == ':')
453 /* Not allowed; only base services can start with ':' */
454 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
455 "Cannot acquire a service starting with ':' such as \"%s\"",
456 _dbus_string_get_const_data (service_name));
458 _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"",
459 _dbus_string_get_const_data (service_name));
464 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
466 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
467 "Connection \"%s\" is not allowed to own the service \"%s\"because "
468 "it is reserved for D-Bus' use only",
469 bus_connection_is_active (connection) ?
470 bus_connection_get_name (connection) :
476 policy = bus_connection_get_policy (connection);
477 _dbus_assert (policy != NULL);
479 /* Note that if sid is #NULL then the bus's own context gets used
480 * in bus_connection_selinux_allows_acquire_service()
482 sid = bus_selinux_id_table_lookup (registry->service_sid_table,
485 if (!bus_selinux_allows_acquire_service (connection, sid,
486 _dbus_string_get_const_data (service_name), error))
489 if (dbus_error_is_set (error) &&
490 dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY))
495 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
496 "Connection \"%s\" is not allowed to own the service \"%s\" due "
498 bus_connection_is_active (connection) ?
499 bus_connection_get_name (connection) :
501 _dbus_string_get_const_data (service_name));
505 if (!bus_client_policy_check_can_own (policy, service_name))
507 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
508 "Connection \"%s\" is not allowed to own the service \"%s\" due "
509 "to security policies in the configuration file",
510 bus_connection_is_active (connection) ?
511 bus_connection_get_name (connection) :
513 _dbus_string_get_const_data (service_name));
517 if (bus_connection_get_n_services_owned (connection) >=
518 bus_context_get_max_services_per_connection (registry->context))
520 dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
521 "Connection \"%s\" is not allowed to own more services "
522 "(increase limits in configuration file if required)",
523 bus_connection_is_active (connection) ?
524 bus_connection_get_name (connection) :
529 service = bus_registry_lookup (registry, service_name);
533 primary_owner = bus_service_get_primary_owner (service);
534 if (primary_owner != NULL)
535 old_owner_conn = primary_owner->conn;
537 old_owner_conn = NULL;
540 old_owner_conn = NULL;
544 service = bus_registry_ensure (registry,
545 service_name, connection, flags,
551 primary_owner = bus_service_get_primary_owner (service);
552 if (primary_owner == NULL)
555 if (old_owner_conn == NULL)
557 _dbus_assert (primary_owner->conn == connection);
559 *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
561 else if (old_owner_conn == connection)
563 bus_owner_set_flags (primary_owner, flags);
564 *result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
566 else if (((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
567 !(bus_service_get_allow_replacement (service))) ||
568 ((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
569 !(flags & DBUS_NAME_FLAG_REPLACE_EXISTING)))
572 BusOwner *temp_owner;
573 /* Since we can't be queued if we are already in the queue
576 link = _bus_service_find_owner_link (service, connection);
579 _dbus_list_unlink (&service->owners, link);
580 temp_owner = (BusOwner *)link->data;
581 bus_owner_unref (temp_owner);
582 _dbus_list_free_link (link);
585 *result = DBUS_REQUEST_NAME_REPLY_EXISTS;
587 else if (!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
588 (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) ||
589 !(bus_service_get_allow_replacement (service))))
591 /* Queue the connection */
592 if (!bus_service_add_owner (service, connection,
597 *result = DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
601 /* Replace the current owner */
603 /* We enqueue the new owner and remove the first one because
604 * that will cause NameAcquired and NameLost messages to
608 if (!bus_service_add_owner (service, connection,
613 if (primary_owner->do_not_queue)
615 if (!bus_service_remove_owner (service, old_owner_conn,
621 if (!bus_service_swap_owner (service, old_owner_conn,
627 _dbus_assert (connection == bus_service_get_primary_owner (service)->conn);
628 *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
631 activation = bus_context_get_activation (registry->context);
632 retval = bus_activation_send_pending_auto_activation_messages (activation,
641 #ifdef ENABLE_KDBUS_TRANSPORT
643 bus_registry_acquire_kdbus_service (BusRegistry *registry,
644 DBusConnection *connection,
645 DBusMessage *message,
646 dbus_uint32_t *result,
647 BusTransaction *transaction,
652 BusActivation *activation;
654 DBusString service_name_real;
655 const DBusString *service_name = &service_name_real;
659 dbus_bool_t rm_owner_daemon = FALSE;
660 const char* conn_unique_name;
662 if (!dbus_message_get_args (message, error,
663 DBUS_TYPE_STRING, &name,
664 DBUS_TYPE_UINT32, &flags,
670 _dbus_string_init_const (&service_name_real, name);
672 if (!_dbus_validate_bus_name (service_name, 0,
673 _dbus_string_get_length (service_name)))
675 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
676 "Requested bus name \"%s\" is not valid",
677 _dbus_string_get_const_data (service_name));
679 _dbus_verbose ("Attempt to acquire invalid service name\n");
684 if (_dbus_string_get_byte (service_name, 0) == ':')
686 /* Not allowed; only base services can start with ':' */
687 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
688 "Cannot acquire a service starting with ':' such as \"%s\"",
689 _dbus_string_get_const_data (service_name));
691 _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"",
692 _dbus_string_get_const_data (service_name));
697 conn_unique_name = dbus_message_get_sender(message);
699 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
701 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
702 "Connection \"%s\" is not allowed to own the service \"%s\"because "
703 "it is reserved for D-Bus' use only",
704 conn_unique_name, DBUS_SERVICE_DBUS);
708 if (!bus_client_policy_check_can_own (bus_connection_get_policy (connection), service_name))
710 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
711 "Connection \"%s\" is not allowed to own the service \"%s\" due "
712 "to security policies in the configuration file",
713 conn_unique_name, _dbus_string_get_const_data (service_name));
717 service = bus_registry_lookup (registry, service_name);
720 service = bus_registry_ensure (registry, service_name, connection, flags,
721 transaction, error); //adds daemon to service owners list - must be removed after right owner is set
725 rm_owner_daemon = TRUE;
726 if(!kdbus_register_policy(service_name, connection))
728 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
729 "Kdbus error when setting policy for connection \"%s\" and service name \"%s\"",
730 conn_unique_name, _dbus_string_get_const_data (service_name));
735 sender_id = sender_name_to_id(conn_unique_name, error);
736 if(dbus_error_is_set(error))
739 *result = kdbus_request_name(connection, service_name, flags, sender_id);
740 if(*result == -EPERM)
742 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
743 "Kdbus not allowed to own the service \"%s\"",
744 _dbus_string_get_const_data (service_name));
749 dbus_set_error (error, DBUS_ERROR_FAILED , "Name \"%s\" could not be acquired", name);
753 if((*result == DBUS_REQUEST_NAME_REPLY_IN_QUEUE) || (*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER))
755 DBusConnection* phantom;
759 name = dbus_message_get_sender(message);
760 phantom = bus_connections_find_conn_by_name(bus_connection_get_connections(connection), name);
762 phantom = create_phantom_connection(connection, name, error);
765 if (!bus_service_add_owner (service, phantom, flags, transaction, error))
767 if((*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) && rm_owner_daemon)
769 /* Here we are removing DBus daemon as an owner of the service,
770 * which is set by bus_registry_ensure.
771 * If bus_service_remove_owner fail, we ignore it, because it has
772 * almost none impact on the usage
774 if(_bus_service_find_owner_link (service, connection))
775 bus_service_remove_owner (service, connection, transaction, NULL);
777 /*if(bus_service_get_is_kdbus_starter(service))
779 if (!bus_service_swap_owner (service, bus_service_get_primary_owners_connection(service),
783 /*if((link = _bus_service_find_owner_link (service, connection))) //if daemon is a starter
785 _dbus_list_unlink (&service->owners, link);
786 _dbus_list_append_link (&service->owners, link); //it must be moved at the end of the queue
790 activation = bus_context_get_activation (registry->context);
791 retval = bus_activation_send_pending_auto_activation_messages (activation,
799 kdbus_release_name(connection, service_name, sender_id);
801 if(_bus_service_find_owner_link (service, connection))
802 bus_service_remove_owner (service, connection, transaction, NULL);
809 bus_registry_release_service (BusRegistry *registry,
810 DBusConnection *connection,
811 const DBusString *service_name,
812 dbus_uint32_t *result,
813 BusTransaction *transaction,
821 if (!_dbus_validate_bus_name (service_name, 0,
822 _dbus_string_get_length (service_name)))
824 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
825 "Given bus name \"%s\" is not valid",
826 _dbus_string_get_const_data (service_name));
828 _dbus_verbose ("Attempt to release invalid service name\n");
833 if (_dbus_string_get_byte (service_name, 0) == ':')
835 /* Not allowed; the base service name cannot be created or released */
836 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
837 "Cannot release a service starting with ':' such as \"%s\"",
838 _dbus_string_get_const_data (service_name));
840 _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
841 _dbus_string_get_const_data (service_name));
846 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
848 /* Not allowed; the base service name cannot be created or released */
849 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
850 "Cannot release the %s service because it is owned by the bus",
853 _dbus_verbose ("Attempt to release service name \"%s\"",
859 service = bus_registry_lookup (registry, service_name);
863 *result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
865 else if (!bus_service_has_owner (service, connection))
867 *result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
871 if (!bus_service_remove_owner (service, connection,
875 _dbus_assert (!bus_service_has_owner (service, connection));
876 *result = DBUS_RELEASE_NAME_REPLY_RELEASED;
885 #ifdef ENABLE_KDBUS_TRANSPORT
887 bus_registry_release_service_kdbus (const char* sender_name,
888 DBusConnection *connection,
889 const DBusString *service_name,
890 dbus_uint32_t *result,
891 BusTransaction *transaction,
894 dbus_bool_t retval = FALSE;
897 if (!_dbus_validate_bus_name (service_name, 0,
898 _dbus_string_get_length (service_name)))
900 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
901 "Given bus name \"%s\" is not valid",
902 _dbus_string_get_const_data (service_name));
904 _dbus_verbose ("Attempt to release invalid service name\n");
909 if (_dbus_string_get_byte (service_name, 0) == ':')
911 /* Not allowed; the base service name cannot be created or released */
912 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
913 "Cannot release a service starting with ':' such as \"%s\"",
914 _dbus_string_get_const_data (service_name));
916 _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
917 _dbus_string_get_const_data (service_name));
922 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
924 /* Not allowed; the base service name cannot be created or released */
925 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
926 "Cannot release the %s service because it is owned by the bus",
929 _dbus_verbose ("Attempt to release service name \"%s\"",
935 sender_id = sender_name_to_id(sender_name, error);
936 if(dbus_error_is_set(error))
939 *result = kdbus_release_name(connection, service_name, sender_id);
941 if(*result == DBUS_RELEASE_NAME_REPLY_RELEASED)
943 BusRegistry* registry;
946 registry = bus_connection_get_registry (connection);
947 service = bus_registry_lookup (registry, service_name);
950 DBusConnection* phantom;
952 phantom = _bus_service_find_owner_connection(service, sender_name);
955 bus_service_remove_owner (service, phantom, transaction, NULL);
956 /* todo we could remove phantom if he doesn't own any name
957 * to do this we should write function in connection.c to check if
958 * _dbus_list_get_last (&d->services_owned) returns not NULL
959 * or we can leave phantom - he will be removed when he disconnects from the bus
963 _dbus_verbose ("Didn't find phantom connection for released name!\n");
975 bus_registry_set_service_context_table (BusRegistry *registry,
976 DBusHashTable *table)
978 DBusHashTable *new_table;
981 new_table = bus_selinux_id_table_new ();
985 _dbus_hash_iter_init (table, &iter);
986 while (_dbus_hash_iter_next (&iter))
988 const char *service = _dbus_hash_iter_get_string_key (&iter);
989 const char *context = _dbus_hash_iter_get_value (&iter);
991 if (!bus_selinux_id_table_insert (new_table,
997 if (registry->service_sid_table)
998 _dbus_hash_table_unref (registry->service_sid_table);
999 registry->service_sid_table = new_table;
1004 bus_service_unlink_owner (BusService *service,
1007 _dbus_list_remove_last (&service->owners, owner);
1008 bus_owner_unref (owner);
1012 bus_service_unlink (BusService *service)
1014 _dbus_assert (service->owners == NULL);
1016 /* the service may not be in the hash, if
1017 * the failure causing transaction cancel
1018 * was in the right place, but that's OK
1020 _dbus_hash_table_remove_string (service->registry->service_hash,
1023 bus_service_unref (service);
1027 bus_service_relink (BusService *service,
1028 DBusPreallocatedHash *preallocated)
1030 _dbus_assert (service->owners == NULL);
1031 _dbus_assert (preallocated != NULL);
1033 _dbus_hash_table_insert_string_preallocated (service->registry->service_hash,
1038 bus_service_ref (service);
1042 * Data used to represent an ownership cancellation in
1043 * a bus transaction.
1047 BusOwner *owner; /**< the owner */
1048 BusService *service; /**< service to cancel ownership of */
1049 } OwnershipCancelData;
1052 cancel_ownership (void *data)
1054 OwnershipCancelData *d = data;
1056 /* We don't need to send messages notifying of these
1057 * changes, since we're reverting something that was
1058 * cancelled (effectively never really happened)
1060 bus_service_unlink_owner (d->service, d->owner);
1062 if (d->service->owners == NULL)
1063 bus_service_unlink (d->service);
1067 free_ownership_cancel_data (void *data)
1069 OwnershipCancelData *d = data;
1071 dbus_connection_unref (d->owner->conn);
1072 bus_owner_unref (d->owner);
1073 bus_service_unref (d->service);
1079 add_cancel_ownership_to_transaction (BusTransaction *transaction,
1080 BusService *service,
1083 OwnershipCancelData *d;
1085 d = dbus_new (OwnershipCancelData, 1);
1089 d->service = service;
1092 if (!bus_transaction_add_cancel_hook (transaction, cancel_ownership, d,
1093 free_ownership_cancel_data))
1099 bus_service_ref (d->service);
1100 bus_owner_ref (owner);
1101 dbus_connection_ref (d->owner->conn);
1106 /* this function is self-cancelling if you cancel the transaction */
1108 bus_service_add_owner (BusService *service,
1109 DBusConnection *connection,
1110 dbus_uint32_t flags,
1111 BusTransaction *transaction,
1114 BusOwner *bus_owner;
1115 DBusList *bus_owner_link;
1117 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1119 /* Send service acquired message first, OOM will result
1120 * in cancelling the transaction
1122 if (service->owners == NULL)
1124 if (!bus_driver_send_service_acquired (connection, service->name, transaction, error))
1128 bus_owner_link = _bus_service_find_owner_link (service, connection);
1130 if (bus_owner_link == NULL)
1132 bus_owner = bus_owner_new (service, connection, flags);
1133 if (bus_owner == NULL)
1135 BUS_SET_OOM (error);
1139 bus_owner_set_flags (bus_owner, flags);
1140 if (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) || service->owners == NULL)
1142 if (!_dbus_list_append (&service->owners,
1145 bus_owner_unref (bus_owner);
1146 BUS_SET_OOM (error);
1152 if (!_dbus_list_insert_after (&service->owners,
1153 _dbus_list_get_first_link (&service->owners),
1156 bus_owner_unref (bus_owner);
1157 BUS_SET_OOM (error);
1164 /* Update the link since we are already in the queue
1165 * No need for operations that can produce OOM
1168 bus_owner = (BusOwner *) bus_owner_link->data;
1169 if (flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
1172 _dbus_list_unlink (&service->owners, bus_owner_link);
1173 link = _dbus_list_get_first_link (&service->owners);
1174 _dbus_assert (link != NULL);
1176 _dbus_list_insert_after_link (&service->owners, link, bus_owner_link);
1179 bus_owner_set_flags (bus_owner, flags);
1183 if (!add_cancel_ownership_to_transaction (transaction,
1187 bus_service_unlink_owner (service, bus_owner);
1188 BUS_SET_OOM (error);
1198 BusService *service;
1199 BusOwner *before_owner; /* restore to position before this connection in owners list */
1200 DBusList *owner_link;
1201 DBusList *service_link;
1202 DBusPreallocatedHash *hash_entry;
1203 } OwnershipRestoreData;
1206 restore_ownership (void *data)
1208 OwnershipRestoreData *d = data;
1211 _dbus_assert (d->service_link != NULL);
1212 _dbus_assert (d->owner_link != NULL);
1214 if (d->service->owners == NULL)
1216 _dbus_assert (d->hash_entry != NULL);
1217 bus_service_relink (d->service, d->hash_entry);
1221 _dbus_assert (d->hash_entry == NULL);
1224 /* We don't need to send messages notifying of these
1225 * changes, since we're reverting something that was
1226 * cancelled (effectively never really happened)
1228 link = _dbus_list_get_first_link (&d->service->owners);
1229 while (link != NULL)
1231 if (link->data == d->before_owner)
1234 link = _dbus_list_get_next_link (&d->service->owners, link);
1237 _dbus_list_insert_before_link (&d->service->owners, link, d->owner_link);
1239 /* Note that removing then restoring this changes the order in which
1240 * ServiceDeleted messages are sent on destruction of the
1241 * connection. This should be OK as the only guarantee there is
1242 * that the base service is destroyed last, and we never even
1243 * tentatively remove the base service.
1245 bus_connection_add_owned_service_link (d->owner->conn, d->service_link);
1247 d->hash_entry = NULL;
1248 d->service_link = NULL;
1249 d->owner_link = NULL;
1253 free_ownership_restore_data (void *data)
1255 OwnershipRestoreData *d = data;
1257 if (d->service_link)
1258 _dbus_list_free_link (d->service_link);
1260 _dbus_list_free_link (d->owner_link);
1262 _dbus_hash_table_free_preallocated_entry (d->service->registry->service_hash,
1265 dbus_connection_unref (d->owner->conn);
1266 bus_owner_unref (d->owner);
1267 bus_service_unref (d->service);
1273 add_restore_ownership_to_transaction (BusTransaction *transaction,
1274 BusService *service,
1277 OwnershipRestoreData *d;
1280 d = dbus_new (OwnershipRestoreData, 1);
1284 d->service = service;
1286 d->service_link = _dbus_list_alloc_link (service);
1287 d->owner_link = _dbus_list_alloc_link (owner);
1288 d->hash_entry = _dbus_hash_table_preallocate_entry (service->registry->service_hash);
1290 bus_service_ref (d->service);
1291 bus_owner_ref (d->owner);
1292 dbus_connection_ref (d->owner->conn);
1294 d->before_owner = NULL;
1295 link = _dbus_list_get_first_link (&service->owners);
1296 while (link != NULL)
1298 if (link->data == owner)
1300 link = _dbus_list_get_next_link (&service->owners, link);
1303 d->before_owner = link->data;
1308 link = _dbus_list_get_next_link (&service->owners, link);
1311 if (d->service_link == NULL ||
1312 d->owner_link == NULL ||
1313 d->hash_entry == NULL ||
1314 !bus_transaction_add_cancel_hook (transaction, restore_ownership, d,
1315 free_ownership_restore_data))
1317 free_ownership_restore_data (d);
1325 bus_service_swap_owner (BusService *service,
1326 DBusConnection *connection,
1327 BusTransaction *transaction,
1330 DBusList *swap_link;
1331 BusOwner *primary_owner;
1333 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1335 /* We send out notifications before we do any work we
1336 * might have to undo if the notification-sending failed
1339 /* Send service lost message */
1340 primary_owner = bus_service_get_primary_owner (service);
1341 if (primary_owner == NULL || primary_owner->conn != connection)
1342 _dbus_assert_not_reached ("Tried to swap a non primary owner");
1345 if (!bus_driver_send_service_lost (connection, service->name,
1346 transaction, error))
1349 if (service->owners == NULL)
1351 _dbus_assert_not_reached ("Tried to swap owner of a service that has no owners");
1353 else if (_dbus_list_length_is_one (&service->owners))
1355 _dbus_assert_not_reached ("Tried to swap owner of a service that has no other owners in the queue");
1360 BusOwner *new_owner;
1361 DBusConnection *new_owner_conn;
1362 link = _dbus_list_get_first_link (&service->owners);
1363 _dbus_assert (link != NULL);
1364 link = _dbus_list_get_next_link (&service->owners, link);
1365 _dbus_assert (link != NULL);
1367 new_owner = (BusOwner *)link->data;
1368 new_owner_conn = new_owner->conn;
1370 if (!bus_driver_send_service_owner_changed (service->name,
1371 bus_connection_get_name (connection),
1372 bus_connection_get_name (new_owner_conn),
1373 transaction, error))
1376 /* This will be our new owner */
1377 if (!bus_driver_send_service_acquired (new_owner_conn,
1384 if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1386 BUS_SET_OOM (error);
1390 /* unlink the primary and make it the second link */
1391 swap_link = _dbus_list_get_first_link (&service->owners);
1392 _dbus_list_unlink (&service->owners, swap_link);
1394 _dbus_list_insert_after_link (&service->owners,
1395 _dbus_list_get_first_link (&service->owners),
1401 /* this function is self-cancelling if you cancel the transaction */
1403 bus_service_remove_owner (BusService *service,
1404 DBusConnection *connection,
1405 BusTransaction *transaction,
1408 BusOwner *primary_owner;
1410 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1412 /* We send out notifications before we do any work we
1413 * might have to undo if the notification-sending failed
1416 /* Send service lost message */
1417 primary_owner = bus_service_get_primary_owner (service);
1418 if (primary_owner != NULL && primary_owner->conn == connection)
1420 if (!bus_driver_send_service_lost (connection, service->name,
1421 transaction, error))
1426 /* if we are not the primary owner then just remove us from the queue */
1428 BusOwner *temp_owner;
1430 link = _bus_service_find_owner_link (service, connection);
1431 _dbus_list_unlink (&service->owners, link);
1432 temp_owner = (BusOwner *)link->data;
1433 bus_owner_unref (temp_owner);
1434 _dbus_list_free_link (link);
1439 if (service->owners == NULL)
1441 _dbus_assert_not_reached ("Tried to remove owner of a service that has no owners");
1443 else if (_dbus_list_length_is_one (&service->owners))
1445 if (!bus_driver_send_service_owner_changed (service->name,
1446 bus_connection_get_name (connection),
1448 transaction, error))
1454 BusOwner *new_owner;
1455 DBusConnection *new_owner_conn;
1456 link = _dbus_list_get_first_link (&service->owners);
1457 _dbus_assert (link != NULL);
1458 link = _dbus_list_get_next_link (&service->owners, link);
1459 _dbus_assert (link != NULL);
1461 new_owner = (BusOwner *)link->data;
1462 new_owner_conn = new_owner->conn;
1464 if (!bus_driver_send_service_owner_changed (service->name,
1465 bus_connection_get_name (connection),
1466 bus_connection_get_name (new_owner_conn),
1467 transaction, error))
1470 /* This will be our new owner */
1471 if (!bus_driver_send_service_acquired (new_owner_conn,
1478 if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1480 BUS_SET_OOM (error);
1484 bus_service_unlink_owner (service, primary_owner);
1486 if (service->owners == NULL)
1487 bus_service_unlink (service);
1493 bus_service_ref (BusService *service)
1495 _dbus_assert (service->refcount > 0);
1497 service->refcount += 1;
1503 bus_service_unref (BusService *service)
1505 _dbus_assert (service->refcount > 0);
1507 service->refcount -= 1;
1509 if (service->refcount == 0)
1511 _dbus_assert (service->owners == NULL);
1513 dbus_free (service->name);
1514 _dbus_mem_pool_dealloc (service->registry->service_pool, service);
1519 bus_service_get_primary_owners_connection (BusService *service)
1522 #ifdef ENABLE_KDBUS_TRANSPORT
1523 char unique_name[(unsigned int)(snprintf((char*)NULL, 0, "%llu", ULLONG_MAX) + sizeof(":1."))];
1526 owner = bus_service_get_primary_owner (service);
1528 #ifdef ENABLE_KDBUS_TRANSPORT
1529 if(kdbus_get_name_owner(owner->conn, bus_service_get_name(service), unique_name) < 0)
1531 return _bus_service_find_owner_connection(service, unique_name); //bus_connections_find_conn_by_name would be safer? but slower
1541 bus_service_get_primary_owner (BusService *service)
1543 return _dbus_list_get_first (&service->owners);
1547 bus_service_get_name (BusService *service)
1549 return service->name;
1553 bus_service_get_allow_replacement (BusService *service)
1558 _dbus_assert (service->owners != NULL);
1560 link = _dbus_list_get_first_link (&service->owners);
1561 owner = (BusOwner *) link->data;
1563 return owner->allow_replacement;
1566 #ifdef ENABLE_KDBUS_TRANSPORT
1568 bus_service_get_is_kdbus_starter (BusService *service)
1573 _dbus_assert (service->owners != NULL);
1575 link = _dbus_list_get_first_link (&service->owners);
1576 owner = (BusOwner *) link->data;
1578 return owner->is_kdbus_starter;
1583 bus_service_has_owner (BusService *service,
1584 DBusConnection *connection)
1588 link = _bus_service_find_owner_link (service, connection);
1597 bus_service_list_queued_owners (BusService *service,
1598 DBusList **return_list,
1603 _dbus_assert (*return_list == NULL);
1605 link = _dbus_list_get_first_link (&service->owners);
1606 _dbus_assert (link != NULL);
1608 while (link != NULL)
1613 owner = (BusOwner *) link->data;
1614 uname = bus_connection_get_name (owner->conn);
1616 #ifdef ENABLE_KDBUS_TRANSPORT
1617 if(!owner->is_kdbus_starter)
1619 if (!_dbus_list_append (return_list, (char *)uname))
1622 link = _dbus_list_get_next_link (&service->owners, link);
1628 _dbus_list_clear (return_list);
1629 BUS_SET_OOM (error);