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>
31 #ifdef ENABLE_KDBUS_TRANSPORT
32 #include <linux/types.h>
39 #include "connection.h"
41 #include "activation.h"
45 #ifdef ENABLE_KDBUS_TRANSPORT
47 #include "dbus/kdbus.h"
54 BusRegistry *registry;
66 unsigned int allow_replacement : 1;
67 unsigned int do_not_queue : 1;
68 #ifdef ENABLE_KDBUS_TRANSPORT
69 unsigned int is_kdbus_starter : 1;
79 DBusHashTable *service_hash;
80 DBusMemPool *service_pool;
81 DBusMemPool *owner_pool;
83 DBusHashTable *service_sid_table;
87 bus_registry_new (BusContext *context)
89 BusRegistry *registry;
91 registry = dbus_new0 (BusRegistry, 1);
95 registry->refcount = 1;
96 registry->context = context;
98 registry->service_hash = _dbus_hash_table_new (DBUS_HASH_STRING,
100 if (registry->service_hash == NULL)
103 registry->service_pool = _dbus_mem_pool_new (sizeof (BusService),
106 if (registry->service_pool == NULL)
109 registry->owner_pool = _dbus_mem_pool_new (sizeof (BusOwner),
112 if (registry->owner_pool == NULL)
115 registry->service_sid_table = NULL;
120 bus_registry_unref (registry);
125 bus_registry_ref (BusRegistry *registry)
127 _dbus_assert (registry->refcount > 0);
128 registry->refcount += 1;
134 bus_registry_unref (BusRegistry *registry)
136 _dbus_assert (registry->refcount > 0);
137 registry->refcount -= 1;
139 if (registry->refcount == 0)
141 if (registry->service_hash)
142 _dbus_hash_table_unref (registry->service_hash);
143 if (registry->service_pool)
144 _dbus_mem_pool_free (registry->service_pool);
145 if (registry->owner_pool)
146 _dbus_mem_pool_free (registry->owner_pool);
147 if (registry->service_sid_table)
148 _dbus_hash_table_unref (registry->service_sid_table);
150 dbus_free (registry);
155 bus_registry_lookup (BusRegistry *registry,
156 const DBusString *service_name)
160 service = _dbus_hash_table_lookup_string (registry->service_hash,
161 _dbus_string_get_const_data (service_name));
167 _bus_service_find_owner_link (BusService *service,
168 DBusConnection *connection)
172 link = _dbus_list_get_first_link (&service->owners);
178 bus_owner = (BusOwner *) link->data;
179 if (bus_owner->conn == connection)
182 link = _dbus_list_get_next_link (&service->owners, link);
188 #ifdef ENABLE_KDBUS_TRANSPORT
189 static DBusConnection *
190 _bus_service_find_owner_connection (BusService *service,
191 const char* unique_name)
195 link = _dbus_list_get_first_link (&service->owners);
201 bus_owner = (BusOwner *) link->data;
202 if(!strcmp(bus_connection_get_name(bus_owner->conn), unique_name))
203 return bus_owner->conn;
205 link = _dbus_list_get_next_link (&service->owners, link);
213 bus_owner_set_flags (BusOwner *owner,
216 owner->allow_replacement =
217 (flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT) != FALSE;
219 owner->do_not_queue =
220 (flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) != FALSE;
222 #ifdef ENABLE_KDBUS_TRANSPORT
223 owner->is_kdbus_starter =
224 (flags & KDBUS_NAME_STARTER) != FALSE;
229 bus_owner_new (BusService *service,
230 DBusConnection *conn,
235 result = _dbus_mem_pool_alloc (service->registry->owner_pool);
238 result->refcount = 1;
239 /* don't ref the connection because we don't want
240 to block the connection from going away.
241 transactions take care of reffing the connection
242 but we need to use refcounting on the owner
243 so that the owner does not get freed before
244 we can deref the connection in the transaction
247 result->service = service;
249 if (!bus_connection_add_owned_service (conn, service))
251 _dbus_mem_pool_dealloc (service->registry->owner_pool, result);
255 bus_owner_set_flags (result, flags);
261 bus_owner_ref (BusOwner *owner)
263 _dbus_assert (owner->refcount > 0);
264 owner->refcount += 1;
270 bus_owner_unref (BusOwner *owner)
272 _dbus_assert (owner->refcount > 0);
273 owner->refcount -= 1;
275 if (owner->refcount == 0)
277 bus_connection_remove_owned_service (owner->conn, owner->service);
278 _dbus_mem_pool_dealloc (owner->service->registry->owner_pool, owner);
283 bus_registry_ensure (BusRegistry *registry,
284 const DBusString *service_name,
285 DBusConnection *owner_connection_if_created,
287 BusTransaction *transaction,
292 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
294 _dbus_assert (owner_connection_if_created != NULL);
295 _dbus_assert (transaction != NULL);
297 service = _dbus_hash_table_lookup_string (registry->service_hash,
298 _dbus_string_get_const_data (service_name));
302 service = _dbus_mem_pool_alloc (registry->service_pool);
309 service->registry = registry;
310 service->refcount = 1;
312 _dbus_verbose ("copying string %p '%s' to service->name\n",
313 service_name, _dbus_string_get_const_data (service_name));
314 if (!_dbus_string_copy_data (service_name, &service->name))
316 _dbus_mem_pool_dealloc (registry->service_pool, service);
320 _dbus_verbose ("copied string %p '%s' to '%s'\n",
321 service_name, _dbus_string_get_const_data (service_name),
324 if (!bus_driver_send_service_owner_changed (service->name,
326 bus_connection_get_name (owner_connection_if_created),
329 bus_service_unref (service);
333 if (!bus_activation_service_created (bus_context_get_activation (registry->context),
334 service->name, transaction, error))
336 bus_service_unref (service);
340 if (!bus_service_add_owner (service, owner_connection_if_created, flags,
343 bus_service_unref (service);
347 if (!_dbus_hash_table_insert_string (registry->service_hash,
351 /* The add_owner gets reverted on transaction cancel */
360 bus_registry_foreach (BusRegistry *registry,
361 BusServiceForeachFunction function,
366 _dbus_hash_iter_init (registry->service_hash, &iter);
367 while (_dbus_hash_iter_next (&iter))
369 BusService *service = _dbus_hash_iter_get_value (&iter);
371 (* function) (service, data);
376 bus_registry_list_services (BusRegistry *registry,
384 len = _dbus_hash_table_get_n_entries (registry->service_hash);
385 retval = dbus_new (char *, len + 1);
390 _dbus_hash_iter_init (registry->service_hash, &iter);
392 while (_dbus_hash_iter_next (&iter))
394 BusService *service = _dbus_hash_iter_get_value (&iter);
396 retval[i] = _dbus_strdup (service->name);
397 if (retval[i] == NULL)
412 for (j = 0; j < i; j++)
413 dbus_free (retval[j]);
420 bus_registry_acquire_service (BusRegistry *registry,
421 DBusConnection *connection,
422 const DBusString *service_name,
424 dbus_uint32_t *result,
425 BusTransaction *transaction,
429 DBusConnection *old_owner_conn;
430 BusClientPolicy *policy;
432 BusActivation *activation;
434 BusOwner *primary_owner;
438 if (!_dbus_validate_bus_name (service_name, 0,
439 _dbus_string_get_length (service_name)))
441 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
442 "Requested bus name \"%s\" is not valid",
443 _dbus_string_get_const_data (service_name));
445 _dbus_verbose ("Attempt to acquire invalid service name\n");
450 if (_dbus_string_get_byte (service_name, 0) == ':')
452 /* Not allowed; only base services can start with ':' */
453 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
454 "Cannot acquire a service starting with ':' such as \"%s\"",
455 _dbus_string_get_const_data (service_name));
457 _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"",
458 _dbus_string_get_const_data (service_name));
463 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
465 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
466 "Connection \"%s\" is not allowed to own the service \"%s\"because "
467 "it is reserved for D-Bus' use only",
468 bus_connection_is_active (connection) ?
469 bus_connection_get_name (connection) :
475 policy = bus_connection_get_policy (connection);
476 _dbus_assert (policy != NULL);
478 /* Note that if sid is #NULL then the bus's own context gets used
479 * in bus_connection_selinux_allows_acquire_service()
481 sid = bus_selinux_id_table_lookup (registry->service_sid_table,
484 if (!bus_selinux_allows_acquire_service (connection, sid,
485 _dbus_string_get_const_data (service_name), error))
488 if (dbus_error_is_set (error) &&
489 dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY))
494 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
495 "Connection \"%s\" is not allowed to own the service \"%s\" due "
497 bus_connection_is_active (connection) ?
498 bus_connection_get_name (connection) :
500 _dbus_string_get_const_data (service_name));
504 if (!bus_client_policy_check_can_own (policy, service_name))
506 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
507 "Connection \"%s\" is not allowed to own the service \"%s\" due "
508 "to security policies in the configuration file",
509 bus_connection_is_active (connection) ?
510 bus_connection_get_name (connection) :
512 _dbus_string_get_const_data (service_name));
516 if (bus_connection_get_n_services_owned (connection) >=
517 bus_context_get_max_services_per_connection (registry->context))
519 dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
520 "Connection \"%s\" is not allowed to own more services "
521 "(increase limits in configuration file if required)",
522 bus_connection_is_active (connection) ?
523 bus_connection_get_name (connection) :
528 service = bus_registry_lookup (registry, service_name);
532 primary_owner = bus_service_get_primary_owner (service);
533 if (primary_owner != NULL)
534 old_owner_conn = primary_owner->conn;
536 old_owner_conn = NULL;
539 old_owner_conn = NULL;
543 service = bus_registry_ensure (registry,
544 service_name, connection, flags,
550 primary_owner = bus_service_get_primary_owner (service);
551 if (primary_owner == NULL)
554 if (old_owner_conn == NULL)
556 _dbus_assert (primary_owner->conn == connection);
558 *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
560 else if (old_owner_conn == connection)
562 bus_owner_set_flags (primary_owner, flags);
563 *result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
565 else if (((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
566 !(bus_service_get_allow_replacement (service))) ||
567 ((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
568 !(flags & DBUS_NAME_FLAG_REPLACE_EXISTING)))
571 BusOwner *temp_owner;
572 /* Since we can't be queued if we are already in the queue
575 link = _bus_service_find_owner_link (service, connection);
578 _dbus_list_unlink (&service->owners, link);
579 temp_owner = (BusOwner *)link->data;
580 bus_owner_unref (temp_owner);
581 _dbus_list_free_link (link);
584 *result = DBUS_REQUEST_NAME_REPLY_EXISTS;
586 else if (!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
587 (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) ||
588 !(bus_service_get_allow_replacement (service))))
590 /* Queue the connection */
591 if (!bus_service_add_owner (service, connection,
596 *result = DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
600 /* Replace the current owner */
602 /* We enqueue the new owner and remove the first one because
603 * that will cause NameAcquired and NameLost messages to
607 if (!bus_service_add_owner (service, connection,
612 if (primary_owner->do_not_queue)
614 if (!bus_service_remove_owner (service, old_owner_conn,
620 if (!bus_service_swap_owner (service, old_owner_conn,
626 _dbus_assert (connection == bus_service_get_primary_owner (service)->conn);
627 *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
630 activation = bus_context_get_activation (registry->context);
631 retval = bus_activation_send_pending_auto_activation_messages (activation,
640 #ifdef ENABLE_KDBUS_TRANSPORT
642 bus_registry_acquire_kdbus_service (BusRegistry *registry,
643 DBusConnection *connection,
644 DBusMessage *message,
645 dbus_uint32_t *result,
646 BusTransaction *transaction,
651 BusActivation *activation;
653 DBusString service_name_real;
654 const DBusString *service_name = &service_name_real;
658 dbus_bool_t rm_owner_daemon = FALSE;
660 if (!dbus_message_get_args (message, error,
661 DBUS_TYPE_STRING, &name,
662 DBUS_TYPE_UINT32, &flags,
668 _dbus_string_init_const (&service_name_real, name);
670 if (!_dbus_validate_bus_name (service_name, 0,
671 _dbus_string_get_length (service_name)))
673 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
674 "Requested bus name \"%s\" is not valid",
675 _dbus_string_get_const_data (service_name));
677 _dbus_verbose ("Attempt to acquire invalid service name\n");
682 if (_dbus_string_get_byte (service_name, 0) == ':')
684 /* Not allowed; only base services can start with ':' */
685 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
686 "Cannot acquire a service starting with ':' such as \"%s\"",
687 _dbus_string_get_const_data (service_name));
689 _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"",
690 _dbus_string_get_const_data (service_name));
695 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
697 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
698 "Connection \"%s\" is not allowed to own the service \"%s\"because "
699 "it is reserved for D-Bus' use only",
700 bus_connection_is_active (connection) ?
701 bus_connection_get_name (connection) :
707 service = bus_registry_lookup (registry, service_name);
710 service = bus_registry_ensure (registry, service_name, connection, flags,
711 transaction, error); //adds daemon to service owners list - must be removed after right owner is set
715 rm_owner_daemon = TRUE;
716 if(!kdbus_register_policy(service_name, connection))
718 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
719 "Connection is not allowed to own the service \"%s\" due to security policies in the configuration file",
720 _dbus_string_get_const_data (service_name));
725 sender_id = sender_name_to_id(dbus_message_get_sender(message), error);
726 if(dbus_error_is_set(error))
729 *result = kdbus_request_name(connection, service_name, flags, sender_id);
730 if(*result == -EPERM)
732 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
733 "Connection is not allowed to own the service \"%s\" due to security policies in the configuration file",
734 _dbus_string_get_const_data (service_name));
739 dbus_set_error (error, DBUS_ERROR_FAILED , "Name \"%s\" could not be acquired", name);
743 if((*result == DBUS_REQUEST_NAME_REPLY_IN_QUEUE) || (*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER))
745 DBusConnection* phantom;
749 name = dbus_message_get_sender(message);
750 phantom = bus_connections_find_conn_by_name(bus_connection_get_connections(connection), name);
752 phantom = create_phantom_connection(connection, name, error);
755 if (!bus_service_add_owner (service, phantom, flags, transaction, error))
757 if((*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) && rm_owner_daemon)
759 /* Here we are removing DBus daemon as an owner of the service,
760 * which is set by bus_registry_ensure.
761 * If bus_service_remove_owner fail, we ignore it, because it has
762 * almost none impact on the usage
764 if(_bus_service_find_owner_link (service, connection))
765 bus_service_remove_owner (service, connection, transaction, NULL);
767 /*if(bus_service_get_is_kdbus_starter(service))
769 if (!bus_service_swap_owner (service, bus_service_get_primary_owners_connection(service),
773 /*if((link = _bus_service_find_owner_link (service, connection))) //if daemon is a starter
775 _dbus_list_unlink (&service->owners, link);
776 _dbus_list_append_link (&service->owners, link); //it must be moved at the end of the queue
780 activation = bus_context_get_activation (registry->context);
781 retval = bus_activation_send_pending_auto_activation_messages (activation,
789 kdbus_release_name(connection, service_name, sender_id);
791 if(_bus_service_find_owner_link (service, connection))
792 bus_service_remove_owner (service, connection, transaction, NULL);
799 bus_registry_release_service (BusRegistry *registry,
800 DBusConnection *connection,
801 const DBusString *service_name,
802 dbus_uint32_t *result,
803 BusTransaction *transaction,
811 if (!_dbus_validate_bus_name (service_name, 0,
812 _dbus_string_get_length (service_name)))
814 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
815 "Given bus name \"%s\" is not valid",
816 _dbus_string_get_const_data (service_name));
818 _dbus_verbose ("Attempt to release invalid service name\n");
823 if (_dbus_string_get_byte (service_name, 0) == ':')
825 /* Not allowed; the base service name cannot be created or released */
826 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
827 "Cannot release a service starting with ':' such as \"%s\"",
828 _dbus_string_get_const_data (service_name));
830 _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
831 _dbus_string_get_const_data (service_name));
836 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
838 /* Not allowed; the base service name cannot be created or released */
839 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
840 "Cannot release the %s service because it is owned by the bus",
843 _dbus_verbose ("Attempt to release service name \"%s\"",
849 service = bus_registry_lookup (registry, service_name);
853 *result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
855 else if (!bus_service_has_owner (service, connection))
857 *result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
861 if (!bus_service_remove_owner (service, connection,
865 _dbus_assert (!bus_service_has_owner (service, connection));
866 *result = DBUS_RELEASE_NAME_REPLY_RELEASED;
875 #ifdef ENABLE_KDBUS_TRANSPORT
877 bus_registry_release_service_kdbus (const char* sender_name,
878 DBusConnection *connection,
879 const DBusString *service_name,
880 dbus_uint32_t *result,
881 BusTransaction *transaction,
884 dbus_bool_t retval = FALSE;
887 if (!_dbus_validate_bus_name (service_name, 0,
888 _dbus_string_get_length (service_name)))
890 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
891 "Given bus name \"%s\" is not valid",
892 _dbus_string_get_const_data (service_name));
894 _dbus_verbose ("Attempt to release invalid service name\n");
899 if (_dbus_string_get_byte (service_name, 0) == ':')
901 /* Not allowed; the base service name cannot be created or released */
902 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
903 "Cannot release a service starting with ':' such as \"%s\"",
904 _dbus_string_get_const_data (service_name));
906 _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
907 _dbus_string_get_const_data (service_name));
912 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
914 /* Not allowed; the base service name cannot be created or released */
915 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
916 "Cannot release the %s service because it is owned by the bus",
919 _dbus_verbose ("Attempt to release service name \"%s\"",
925 sender_id = sender_name_to_id(sender_name, error);
926 if(dbus_error_is_set(error))
929 *result = kdbus_release_name(connection, service_name, sender_id);
931 if(*result == DBUS_RELEASE_NAME_REPLY_RELEASED)
933 BusRegistry* registry;
936 registry = bus_connection_get_registry (connection);
937 service = bus_registry_lookup (registry, service_name);
940 DBusConnection* phantom;
942 phantom = _bus_service_find_owner_connection(service, sender_name);
945 bus_service_remove_owner (service, phantom, transaction, NULL);
946 /* todo we could remove phantom if he doesn't own any name
947 * to do this we should write function in connection.c to check if
948 * _dbus_list_get_last (&d->services_owned) returns not NULL
949 * or we can leave phantom - he will be removed when he disconnects from the bus
953 _dbus_verbose ("Didn't find phantom connection for released name!\n");
965 bus_registry_set_service_context_table (BusRegistry *registry,
966 DBusHashTable *table)
968 DBusHashTable *new_table;
971 new_table = bus_selinux_id_table_new ();
975 _dbus_hash_iter_init (table, &iter);
976 while (_dbus_hash_iter_next (&iter))
978 const char *service = _dbus_hash_iter_get_string_key (&iter);
979 const char *context = _dbus_hash_iter_get_value (&iter);
981 if (!bus_selinux_id_table_insert (new_table,
987 if (registry->service_sid_table)
988 _dbus_hash_table_unref (registry->service_sid_table);
989 registry->service_sid_table = new_table;
994 bus_service_unlink_owner (BusService *service,
997 _dbus_list_remove_last (&service->owners, owner);
998 bus_owner_unref (owner);
1002 bus_service_unlink (BusService *service)
1004 _dbus_assert (service->owners == NULL);
1006 /* the service may not be in the hash, if
1007 * the failure causing transaction cancel
1008 * was in the right place, but that's OK
1010 _dbus_hash_table_remove_string (service->registry->service_hash,
1013 bus_service_unref (service);
1017 bus_service_relink (BusService *service,
1018 DBusPreallocatedHash *preallocated)
1020 _dbus_assert (service->owners == NULL);
1021 _dbus_assert (preallocated != NULL);
1023 _dbus_hash_table_insert_string_preallocated (service->registry->service_hash,
1028 bus_service_ref (service);
1032 * Data used to represent an ownership cancellation in
1033 * a bus transaction.
1037 BusOwner *owner; /**< the owner */
1038 BusService *service; /**< service to cancel ownership of */
1039 } OwnershipCancelData;
1042 cancel_ownership (void *data)
1044 OwnershipCancelData *d = data;
1046 /* We don't need to send messages notifying of these
1047 * changes, since we're reverting something that was
1048 * cancelled (effectively never really happened)
1050 bus_service_unlink_owner (d->service, d->owner);
1052 if (d->service->owners == NULL)
1053 bus_service_unlink (d->service);
1057 free_ownership_cancel_data (void *data)
1059 OwnershipCancelData *d = data;
1061 dbus_connection_unref (d->owner->conn);
1062 bus_owner_unref (d->owner);
1063 bus_service_unref (d->service);
1069 add_cancel_ownership_to_transaction (BusTransaction *transaction,
1070 BusService *service,
1073 OwnershipCancelData *d;
1075 d = dbus_new (OwnershipCancelData, 1);
1079 d->service = service;
1082 if (!bus_transaction_add_cancel_hook (transaction, cancel_ownership, d,
1083 free_ownership_cancel_data))
1089 bus_service_ref (d->service);
1090 bus_owner_ref (owner);
1091 dbus_connection_ref (d->owner->conn);
1096 /* this function is self-cancelling if you cancel the transaction */
1098 bus_service_add_owner (BusService *service,
1099 DBusConnection *connection,
1100 dbus_uint32_t flags,
1101 BusTransaction *transaction,
1104 BusOwner *bus_owner;
1105 DBusList *bus_owner_link;
1107 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1109 /* Send service acquired message first, OOM will result
1110 * in cancelling the transaction
1112 if (service->owners == NULL)
1114 if (!bus_driver_send_service_acquired (connection, service->name, transaction, error))
1118 bus_owner_link = _bus_service_find_owner_link (service, connection);
1120 if (bus_owner_link == NULL)
1122 bus_owner = bus_owner_new (service, connection, flags);
1123 if (bus_owner == NULL)
1125 BUS_SET_OOM (error);
1129 bus_owner_set_flags (bus_owner, flags);
1130 if (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) || service->owners == NULL)
1132 if (!_dbus_list_append (&service->owners,
1135 bus_owner_unref (bus_owner);
1136 BUS_SET_OOM (error);
1142 if (!_dbus_list_insert_after (&service->owners,
1143 _dbus_list_get_first_link (&service->owners),
1146 bus_owner_unref (bus_owner);
1147 BUS_SET_OOM (error);
1154 /* Update the link since we are already in the queue
1155 * No need for operations that can produce OOM
1158 bus_owner = (BusOwner *) bus_owner_link->data;
1159 if (flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
1162 _dbus_list_unlink (&service->owners, bus_owner_link);
1163 link = _dbus_list_get_first_link (&service->owners);
1164 _dbus_assert (link != NULL);
1166 _dbus_list_insert_after_link (&service->owners, link, bus_owner_link);
1169 bus_owner_set_flags (bus_owner, flags);
1173 if (!add_cancel_ownership_to_transaction (transaction,
1177 bus_service_unlink_owner (service, bus_owner);
1178 BUS_SET_OOM (error);
1188 BusService *service;
1189 BusOwner *before_owner; /* restore to position before this connection in owners list */
1190 DBusList *owner_link;
1191 DBusList *service_link;
1192 DBusPreallocatedHash *hash_entry;
1193 } OwnershipRestoreData;
1196 restore_ownership (void *data)
1198 OwnershipRestoreData *d = data;
1201 _dbus_assert (d->service_link != NULL);
1202 _dbus_assert (d->owner_link != NULL);
1204 if (d->service->owners == NULL)
1206 _dbus_assert (d->hash_entry != NULL);
1207 bus_service_relink (d->service, d->hash_entry);
1211 _dbus_assert (d->hash_entry == NULL);
1214 /* We don't need to send messages notifying of these
1215 * changes, since we're reverting something that was
1216 * cancelled (effectively never really happened)
1218 link = _dbus_list_get_first_link (&d->service->owners);
1219 while (link != NULL)
1221 if (link->data == d->before_owner)
1224 link = _dbus_list_get_next_link (&d->service->owners, link);
1227 _dbus_list_insert_before_link (&d->service->owners, link, d->owner_link);
1229 /* Note that removing then restoring this changes the order in which
1230 * ServiceDeleted messages are sent on destruction of the
1231 * connection. This should be OK as the only guarantee there is
1232 * that the base service is destroyed last, and we never even
1233 * tentatively remove the base service.
1235 bus_connection_add_owned_service_link (d->owner->conn, d->service_link);
1237 d->hash_entry = NULL;
1238 d->service_link = NULL;
1239 d->owner_link = NULL;
1243 free_ownership_restore_data (void *data)
1245 OwnershipRestoreData *d = data;
1247 if (d->service_link)
1248 _dbus_list_free_link (d->service_link);
1250 _dbus_list_free_link (d->owner_link);
1252 _dbus_hash_table_free_preallocated_entry (d->service->registry->service_hash,
1255 dbus_connection_unref (d->owner->conn);
1256 bus_owner_unref (d->owner);
1257 bus_service_unref (d->service);
1263 add_restore_ownership_to_transaction (BusTransaction *transaction,
1264 BusService *service,
1267 OwnershipRestoreData *d;
1270 d = dbus_new (OwnershipRestoreData, 1);
1274 d->service = service;
1276 d->service_link = _dbus_list_alloc_link (service);
1277 d->owner_link = _dbus_list_alloc_link (owner);
1278 d->hash_entry = _dbus_hash_table_preallocate_entry (service->registry->service_hash);
1280 bus_service_ref (d->service);
1281 bus_owner_ref (d->owner);
1282 dbus_connection_ref (d->owner->conn);
1284 d->before_owner = NULL;
1285 link = _dbus_list_get_first_link (&service->owners);
1286 while (link != NULL)
1288 if (link->data == owner)
1290 link = _dbus_list_get_next_link (&service->owners, link);
1293 d->before_owner = link->data;
1298 link = _dbus_list_get_next_link (&service->owners, link);
1301 if (d->service_link == NULL ||
1302 d->owner_link == NULL ||
1303 d->hash_entry == NULL ||
1304 !bus_transaction_add_cancel_hook (transaction, restore_ownership, d,
1305 free_ownership_restore_data))
1307 free_ownership_restore_data (d);
1315 bus_service_swap_owner (BusService *service,
1316 DBusConnection *connection,
1317 BusTransaction *transaction,
1320 DBusList *swap_link;
1321 BusOwner *primary_owner;
1323 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1325 /* We send out notifications before we do any work we
1326 * might have to undo if the notification-sending failed
1329 /* Send service lost message */
1330 primary_owner = bus_service_get_primary_owner (service);
1331 if (primary_owner == NULL || primary_owner->conn != connection)
1332 _dbus_assert_not_reached ("Tried to swap a non primary owner");
1335 if (!bus_driver_send_service_lost (connection, service->name,
1336 transaction, error))
1339 if (service->owners == NULL)
1341 _dbus_assert_not_reached ("Tried to swap owner of a service that has no owners");
1343 else if (_dbus_list_length_is_one (&service->owners))
1345 _dbus_assert_not_reached ("Tried to swap owner of a service that has no other owners in the queue");
1350 BusOwner *new_owner;
1351 DBusConnection *new_owner_conn;
1352 link = _dbus_list_get_first_link (&service->owners);
1353 _dbus_assert (link != NULL);
1354 link = _dbus_list_get_next_link (&service->owners, link);
1355 _dbus_assert (link != NULL);
1357 new_owner = (BusOwner *)link->data;
1358 new_owner_conn = new_owner->conn;
1360 if (!bus_driver_send_service_owner_changed (service->name,
1361 bus_connection_get_name (connection),
1362 bus_connection_get_name (new_owner_conn),
1363 transaction, error))
1366 /* This will be our new owner */
1367 if (!bus_driver_send_service_acquired (new_owner_conn,
1374 if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1376 BUS_SET_OOM (error);
1380 /* unlink the primary and make it the second link */
1381 swap_link = _dbus_list_get_first_link (&service->owners);
1382 _dbus_list_unlink (&service->owners, swap_link);
1384 _dbus_list_insert_after_link (&service->owners,
1385 _dbus_list_get_first_link (&service->owners),
1391 /* this function is self-cancelling if you cancel the transaction */
1393 bus_service_remove_owner (BusService *service,
1394 DBusConnection *connection,
1395 BusTransaction *transaction,
1398 BusOwner *primary_owner;
1400 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1402 /* We send out notifications before we do any work we
1403 * might have to undo if the notification-sending failed
1406 /* Send service lost message */
1407 primary_owner = bus_service_get_primary_owner (service);
1408 if (primary_owner != NULL && primary_owner->conn == connection)
1410 if (!bus_driver_send_service_lost (connection, service->name,
1411 transaction, error))
1416 /* if we are not the primary owner then just remove us from the queue */
1418 BusOwner *temp_owner;
1420 link = _bus_service_find_owner_link (service, connection);
1421 _dbus_list_unlink (&service->owners, link);
1422 temp_owner = (BusOwner *)link->data;
1423 bus_owner_unref (temp_owner);
1424 _dbus_list_free_link (link);
1429 if (service->owners == NULL)
1431 _dbus_assert_not_reached ("Tried to remove owner of a service that has no owners");
1433 else if (_dbus_list_length_is_one (&service->owners))
1435 if (!bus_driver_send_service_owner_changed (service->name,
1436 bus_connection_get_name (connection),
1438 transaction, error))
1444 BusOwner *new_owner;
1445 DBusConnection *new_owner_conn;
1446 link = _dbus_list_get_first_link (&service->owners);
1447 _dbus_assert (link != NULL);
1448 link = _dbus_list_get_next_link (&service->owners, link);
1449 _dbus_assert (link != NULL);
1451 new_owner = (BusOwner *)link->data;
1452 new_owner_conn = new_owner->conn;
1454 if (!bus_driver_send_service_owner_changed (service->name,
1455 bus_connection_get_name (connection),
1456 bus_connection_get_name (new_owner_conn),
1457 transaction, error))
1460 /* This will be our new owner */
1461 if (!bus_driver_send_service_acquired (new_owner_conn,
1468 if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1470 BUS_SET_OOM (error);
1474 bus_service_unlink_owner (service, primary_owner);
1476 if (service->owners == NULL)
1477 bus_service_unlink (service);
1483 bus_service_ref (BusService *service)
1485 _dbus_assert (service->refcount > 0);
1487 service->refcount += 1;
1493 bus_service_unref (BusService *service)
1495 _dbus_assert (service->refcount > 0);
1497 service->refcount -= 1;
1499 if (service->refcount == 0)
1501 _dbus_assert (service->owners == NULL);
1503 dbus_free (service->name);
1504 _dbus_mem_pool_dealloc (service->registry->service_pool, service);
1509 bus_service_get_primary_owners_connection (BusService *service)
1513 owner = bus_service_get_primary_owner (service);
1522 bus_service_get_primary_owner (BusService *service)
1524 return _dbus_list_get_first (&service->owners);
1528 bus_service_get_name (BusService *service)
1530 return service->name;
1534 bus_service_get_allow_replacement (BusService *service)
1539 _dbus_assert (service->owners != NULL);
1541 link = _dbus_list_get_first_link (&service->owners);
1542 owner = (BusOwner *) link->data;
1544 return owner->allow_replacement;
1547 #ifdef ENABLE_KDBUS_TRANSPORT
1549 bus_service_get_is_kdbus_starter (BusService *service)
1554 _dbus_assert (service->owners != NULL);
1556 link = _dbus_list_get_first_link (&service->owners);
1557 owner = (BusOwner *) link->data;
1559 return owner->is_kdbus_starter;
1564 bus_service_has_owner (BusService *service,
1565 DBusConnection *connection)
1569 link = _bus_service_find_owner_link (service, connection);
1578 bus_service_list_queued_owners (BusService *service,
1579 DBusList **return_list,
1584 _dbus_assert (*return_list == NULL);
1586 link = _dbus_list_get_first_link (&service->owners);
1587 _dbus_assert (link != NULL);
1589 while (link != NULL)
1594 owner = (BusOwner *) link->data;
1595 uname = bus_connection_get_name (owner->conn);
1597 #ifdef ENABLE_KDBUS_TRANSPORT
1598 if(!owner->is_kdbus_starter)
1600 if (!_dbus_list_append (return_list, (char *)uname))
1603 link = _dbus_list_get_next_link (&service->owners, link);
1609 _dbus_list_clear (return_list);
1610 BUS_SET_OOM (error);