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"
49 #include "dbus/kdbus-common.h"
56 BusRegistry *registry;
68 unsigned int allow_replacement : 1;
69 unsigned int do_not_queue : 1;
70 #ifdef ENABLE_KDBUS_TRANSPORT
71 unsigned int is_kdbus_starter : 1;
81 DBusHashTable *service_hash;
82 DBusMemPool *service_pool;
83 DBusMemPool *owner_pool;
85 DBusHashTable *service_sid_table;
89 bus_registry_new (BusContext *context)
91 BusRegistry *registry;
93 registry = dbus_new0 (BusRegistry, 1);
97 registry->refcount = 1;
98 registry->context = context;
100 registry->service_hash = _dbus_hash_table_new (DBUS_HASH_STRING,
102 if (registry->service_hash == NULL)
105 registry->service_pool = _dbus_mem_pool_new (sizeof (BusService),
108 if (registry->service_pool == NULL)
111 registry->owner_pool = _dbus_mem_pool_new (sizeof (BusOwner),
114 if (registry->owner_pool == NULL)
117 registry->service_sid_table = NULL;
122 bus_registry_unref (registry);
127 bus_registry_ref (BusRegistry *registry)
129 _dbus_assert (registry->refcount > 0);
130 registry->refcount += 1;
136 bus_registry_unref (BusRegistry *registry)
138 _dbus_assert (registry->refcount > 0);
139 registry->refcount -= 1;
141 if (registry->refcount == 0)
143 if (registry->service_hash)
144 _dbus_hash_table_unref (registry->service_hash);
145 if (registry->service_pool)
146 _dbus_mem_pool_free (registry->service_pool);
147 if (registry->owner_pool)
148 _dbus_mem_pool_free (registry->owner_pool);
149 if (registry->service_sid_table)
150 _dbus_hash_table_unref (registry->service_sid_table);
152 dbus_free (registry);
157 bus_registry_lookup (BusRegistry *registry,
158 const DBusString *service_name)
162 service = _dbus_hash_table_lookup_string (registry->service_hash,
163 _dbus_string_get_const_data (service_name));
169 _bus_service_find_owner_link (BusService *service,
170 DBusConnection *connection)
174 link = _dbus_list_get_first_link (&service->owners);
180 bus_owner = (BusOwner *) link->data;
181 if (bus_owner->conn == connection)
184 link = _dbus_list_get_next_link (&service->owners, link);
190 #ifdef ENABLE_KDBUS_TRANSPORT
191 static DBusConnection *
192 _bus_service_find_owner_connection (BusService *service,
193 const char* unique_name)
197 link = _dbus_list_get_first_link (&service->owners);
203 bus_owner = (BusOwner *) link->data;
204 if(!strcmp(bus_connection_get_name(bus_owner->conn), unique_name))
205 return bus_owner->conn;
207 link = _dbus_list_get_next_link (&service->owners, link);
215 bus_owner_set_flags (BusOwner *owner,
218 owner->allow_replacement =
219 (flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT) != FALSE;
221 owner->do_not_queue =
222 (flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) != FALSE;
224 #ifdef ENABLE_KDBUS_TRANSPORT
225 owner->is_kdbus_starter =
226 (flags & KDBUS_NAME_STARTER_NAME) != FALSE;
231 bus_owner_new (BusService *service,
232 DBusConnection *conn,
237 result = _dbus_mem_pool_alloc (service->registry->owner_pool);
240 result->refcount = 1;
241 /* don't ref the connection because we don't want
242 to block the connection from going away.
243 transactions take care of reffing the connection
244 but we need to use refcounting on the owner
245 so that the owner does not get freed before
246 we can deref the connection in the transaction
249 result->service = service;
251 if (!bus_connection_add_owned_service (conn, service))
253 _dbus_mem_pool_dealloc (service->registry->owner_pool, result);
257 bus_owner_set_flags (result, flags);
263 bus_owner_ref (BusOwner *owner)
265 _dbus_assert (owner->refcount > 0);
266 owner->refcount += 1;
272 bus_owner_unref (BusOwner *owner)
274 _dbus_assert (owner->refcount > 0);
275 owner->refcount -= 1;
277 if (owner->refcount == 0)
279 bus_connection_remove_owned_service (owner->conn, owner->service);
280 _dbus_mem_pool_dealloc (owner->service->registry->owner_pool, owner);
285 bus_registry_ensure (BusRegistry *registry,
286 const DBusString *service_name,
287 DBusConnection *owner_connection_if_created,
289 BusTransaction *transaction,
294 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
296 _dbus_assert (owner_connection_if_created != NULL);
297 _dbus_assert (transaction != NULL);
299 service = _dbus_hash_table_lookup_string (registry->service_hash,
300 _dbus_string_get_const_data (service_name));
304 service = _dbus_mem_pool_alloc (registry->service_pool);
311 service->registry = registry;
312 service->refcount = 1;
314 _dbus_verbose ("copying string %p '%s' to service->name\n",
315 service_name, _dbus_string_get_const_data (service_name));
316 if (!_dbus_string_copy_data (service_name, &service->name))
318 _dbus_mem_pool_dealloc (registry->service_pool, service);
322 _dbus_verbose ("copied string %p '%s' to '%s'\n",
323 service_name, _dbus_string_get_const_data (service_name),
326 if (!bus_driver_send_service_owner_changed (service->name,
328 bus_connection_get_name (owner_connection_if_created),
331 bus_service_unref (service);
335 if (!bus_activation_service_created (bus_context_get_activation (registry->context),
336 service->name, transaction, error))
338 bus_service_unref (service);
342 if (!bus_service_add_owner (service, owner_connection_if_created, flags,
345 bus_service_unref (service);
349 if (!_dbus_hash_table_insert_string (registry->service_hash,
353 /* The add_owner gets reverted on transaction cancel */
362 bus_registry_foreach (BusRegistry *registry,
363 BusServiceForeachFunction function,
368 _dbus_hash_iter_init (registry->service_hash, &iter);
369 while (_dbus_hash_iter_next (&iter))
371 BusService *service = _dbus_hash_iter_get_value (&iter);
373 (* function) (service, data);
378 bus_registry_list_services (BusRegistry *registry,
386 len = _dbus_hash_table_get_n_entries (registry->service_hash);
387 retval = dbus_new (char *, len + 1);
392 _dbus_hash_iter_init (registry->service_hash, &iter);
394 while (_dbus_hash_iter_next (&iter))
396 BusService *service = _dbus_hash_iter_get_value (&iter);
398 retval[i] = _dbus_strdup (service->name);
399 if (retval[i] == NULL)
414 for (j = 0; j < i; j++)
415 dbus_free (retval[j]);
422 bus_registry_acquire_service (BusRegistry *registry,
423 DBusConnection *connection,
424 const DBusString *service_name,
426 dbus_uint32_t *result,
427 BusTransaction *transaction,
431 DBusConnection *old_owner_conn;
432 BusClientPolicy *policy;
434 BusActivation *activation;
436 BusOwner *primary_owner;
440 if (!_dbus_validate_bus_name (service_name, 0,
441 _dbus_string_get_length (service_name)))
443 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
444 "Requested bus name \"%s\" is not valid",
445 _dbus_string_get_const_data (service_name));
447 _dbus_verbose ("Attempt to acquire invalid service name\n");
452 if (_dbus_string_get_byte (service_name, 0) == ':')
454 /* Not allowed; only base services can start with ':' */
455 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
456 "Cannot acquire a service starting with ':' such as \"%s\"",
457 _dbus_string_get_const_data (service_name));
459 _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"",
460 _dbus_string_get_const_data (service_name));
465 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
467 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
468 "Connection \"%s\" is not allowed to own the service \"%s\"because "
469 "it is reserved for D-Bus' use only",
470 bus_connection_is_active (connection) ?
471 bus_connection_get_name (connection) :
477 policy = bus_connection_get_policy (connection);
478 _dbus_assert (policy != NULL);
480 /* Note that if sid is #NULL then the bus's own context gets used
481 * in bus_connection_selinux_allows_acquire_service()
483 sid = bus_selinux_id_table_lookup (registry->service_sid_table,
486 if (!bus_selinux_allows_acquire_service (connection, sid,
487 _dbus_string_get_const_data (service_name), error))
490 if (dbus_error_is_set (error) &&
491 dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY))
496 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
497 "Connection \"%s\" is not allowed to own the service \"%s\" due "
499 bus_connection_is_active (connection) ?
500 bus_connection_get_name (connection) :
502 _dbus_string_get_const_data (service_name));
506 if (!bus_client_policy_check_can_own (policy, service_name))
508 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
509 "Connection \"%s\" is not allowed to own the service \"%s\" due "
510 "to security policies in the configuration file",
511 bus_connection_is_active (connection) ?
512 bus_connection_get_name (connection) :
514 _dbus_string_get_const_data (service_name));
518 if (bus_connection_get_n_services_owned (connection) >=
519 bus_context_get_max_services_per_connection (registry->context))
521 dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
522 "Connection \"%s\" is not allowed to own more services "
523 "(increase limits in configuration file if required)",
524 bus_connection_is_active (connection) ?
525 bus_connection_get_name (connection) :
530 service = bus_registry_lookup (registry, service_name);
534 primary_owner = bus_service_get_primary_owner (service);
535 if (primary_owner != NULL)
536 old_owner_conn = primary_owner->conn;
538 old_owner_conn = NULL;
541 old_owner_conn = NULL;
545 service = bus_registry_ensure (registry,
546 service_name, connection, flags,
552 primary_owner = bus_service_get_primary_owner (service);
553 if (primary_owner == NULL)
556 if (old_owner_conn == NULL)
558 _dbus_assert (primary_owner->conn == connection);
560 *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
562 else if (old_owner_conn == connection)
564 bus_owner_set_flags (primary_owner, flags);
565 *result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
567 else if (((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
568 !(bus_service_get_allow_replacement (service))) ||
569 ((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
570 !(flags & DBUS_NAME_FLAG_REPLACE_EXISTING)))
573 BusOwner *temp_owner;
574 /* Since we can't be queued if we are already in the queue
577 link = _bus_service_find_owner_link (service, connection);
580 _dbus_list_unlink (&service->owners, link);
581 temp_owner = (BusOwner *)link->data;
582 bus_owner_unref (temp_owner);
583 _dbus_list_free_link (link);
586 *result = DBUS_REQUEST_NAME_REPLY_EXISTS;
588 else if (!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
589 (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) ||
590 !(bus_service_get_allow_replacement (service))))
592 /* Queue the connection */
593 if (!bus_service_add_owner (service, connection,
598 *result = DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
602 /* Replace the current owner */
604 /* We enqueue the new owner and remove the first one because
605 * that will cause NameAcquired and NameLost messages to
609 if (!bus_service_add_owner (service, connection,
614 if (primary_owner->do_not_queue)
616 if (!bus_service_remove_owner (service, old_owner_conn,
622 if (!bus_service_swap_owner (service, old_owner_conn,
628 _dbus_assert (connection == bus_service_get_primary_owner (service)->conn);
629 *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
632 activation = bus_context_get_activation (registry->context);
633 retval = bus_activation_send_pending_auto_activation_messages (activation,
642 #ifdef ENABLE_KDBUS_TRANSPORT
644 bus_registry_acquire_kdbus_service (BusRegistry *registry,
645 DBusConnection *connection,
646 DBusMessage *message,
647 dbus_uint32_t *result,
648 BusTransaction *transaction,
653 BusActivation *activation;
654 DBusString service_name_real;
655 const DBusString *service_name = &service_name_real;
659 const char* conn_unique_name;
660 DBusConnection* phantom;
661 unsigned long int uid;
663 if (!dbus_message_get_args (message, error,
664 DBUS_TYPE_STRING, &name,
665 DBUS_TYPE_UINT32, &flags,
671 _dbus_string_init_const (&service_name_real, name);
673 if (!_dbus_validate_bus_name (service_name, 0,
674 _dbus_string_get_length (service_name)))
676 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
677 "Requested bus name \"%s\" is not valid", 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\"", name);
690 _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"", name);
695 conn_unique_name = dbus_message_get_sender(message);
697 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
699 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
700 "Connection \"%s\" is not allowed to own the service \"%s\"because "
701 "it is reserved for D-Bus' use only",
702 conn_unique_name, DBUS_SERVICE_DBUS);
706 sender_id = sender_name_to_id(conn_unique_name, error);
707 if(dbus_error_is_set(error))
710 phantom = bus_connections_find_conn_by_name(bus_connection_get_connections(connection), conn_unique_name);
713 phantom = create_phantom_connection(connection, conn_unique_name, error);
718 if (!bus_client_policy_check_can_own (bus_connection_get_policy (phantom), service_name))
720 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
721 "Connection \"%s\" is not allowed to own the service \"%s\" due "
722 "to security policies in the configuration file", conn_unique_name, name);
726 if (!kdbus_get_unix_user(phantom, conn_unique_name, &uid, NULL))
729 #ifdef POLICY_TO_KDBUS
730 if (!register_kdbus_policy(name, dbus_connection_get_transport(phantom), uid))
732 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
733 "Kdbus error when setting policy for connection \"%s\" and service name \"%s\"",
734 conn_unique_name, name);
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 %s to own the service \"%s\"",
744 conn_unique_name, _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 service = bus_registry_lookup (registry, service_name);
758 service = bus_registry_ensure (registry, service_name, phantom, flags,
765 if (!bus_service_add_owner (service, phantom, flags, transaction, error))
769 activation = bus_context_get_activation (registry->context);
770 retval = bus_activation_send_pending_auto_activation_messages (activation,
781 kdbus_release_name(phantom, service_name, sender_id);
783 bus_connection_disconnected(phantom);
790 bus_registry_release_service (BusRegistry *registry,
791 DBusConnection *connection,
792 const DBusString *service_name,
793 dbus_uint32_t *result,
794 BusTransaction *transaction,
802 if (!_dbus_validate_bus_name (service_name, 0,
803 _dbus_string_get_length (service_name)))
805 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
806 "Given bus name \"%s\" is not valid",
807 _dbus_string_get_const_data (service_name));
809 _dbus_verbose ("Attempt to release invalid service name\n");
814 if (_dbus_string_get_byte (service_name, 0) == ':')
816 /* Not allowed; the base service name cannot be created or released */
817 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
818 "Cannot release a service starting with ':' such as \"%s\"",
819 _dbus_string_get_const_data (service_name));
821 _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
822 _dbus_string_get_const_data (service_name));
827 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
829 /* Not allowed; the base service name cannot be created or released */
830 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
831 "Cannot release the %s service because it is owned by the bus",
834 _dbus_verbose ("Attempt to release service name \"%s\"",
840 service = bus_registry_lookup (registry, service_name);
844 *result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
846 else if (!bus_service_has_owner (service, connection))
848 *result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
852 if (!bus_service_remove_owner (service, connection,
856 _dbus_assert (!bus_service_has_owner (service, connection));
857 *result = DBUS_RELEASE_NAME_REPLY_RELEASED;
866 #ifdef ENABLE_KDBUS_TRANSPORT
868 bus_registry_release_service_kdbus (const char* sender_name,
869 DBusConnection *connection,
870 const DBusString *service_name,
871 dbus_uint32_t *result,
872 BusTransaction *transaction,
875 dbus_bool_t retval = FALSE;
878 if (!_dbus_validate_bus_name (service_name, 0,
879 _dbus_string_get_length (service_name)))
881 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
882 "Given bus name \"%s\" is not valid",
883 _dbus_string_get_const_data (service_name));
885 _dbus_verbose ("Attempt to release invalid service name\n");
890 if (_dbus_string_get_byte (service_name, 0) == ':')
892 /* Not allowed; the base service name cannot be created or released */
893 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
894 "Cannot release a service starting with ':' such as \"%s\"",
895 _dbus_string_get_const_data (service_name));
897 _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
898 _dbus_string_get_const_data (service_name));
903 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
905 /* Not allowed; the base service name cannot be created or released */
906 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
907 "Cannot release the %s service because it is owned by the bus",
910 _dbus_verbose ("Attempt to release service name \"%s\"",
916 sender_id = sender_name_to_id(sender_name, error);
917 if(dbus_error_is_set(error))
920 *result = kdbus_release_name(connection, service_name, sender_id);
922 if(*result == DBUS_RELEASE_NAME_REPLY_RELEASED)
924 BusRegistry* registry;
927 registry = bus_connection_get_registry (connection);
928 service = bus_registry_lookup (registry, service_name);
931 DBusConnection* phantom;
933 phantom = _bus_service_find_owner_connection(service, sender_name);
936 bus_service_remove_owner (service, phantom, transaction, NULL);
937 /* todo we could remove phantom if he doesn't own any name
938 * to do this we should write function in connection.c to check if
939 * _dbus_list_get_last (&d->services_owned) returns not NULL
940 * or we can leave phantom - he will be removed when he disconnects from the bus
944 _dbus_verbose ("Didn't find phantom connection for released name!\n");
956 bus_registry_set_service_context_table (BusRegistry *registry,
957 DBusHashTable *table)
959 DBusHashTable *new_table;
962 new_table = bus_selinux_id_table_new ();
966 _dbus_hash_iter_init (table, &iter);
967 while (_dbus_hash_iter_next (&iter))
969 const char *service = _dbus_hash_iter_get_string_key (&iter);
970 const char *context = _dbus_hash_iter_get_value (&iter);
972 if (!bus_selinux_id_table_insert (new_table,
978 if (registry->service_sid_table)
979 _dbus_hash_table_unref (registry->service_sid_table);
980 registry->service_sid_table = new_table;
985 bus_service_unlink_owner (BusService *service,
988 _dbus_list_remove_last (&service->owners, owner);
989 bus_owner_unref (owner);
993 bus_service_unlink (BusService *service)
995 _dbus_assert (service->owners == NULL);
997 /* the service may not be in the hash, if
998 * the failure causing transaction cancel
999 * was in the right place, but that's OK
1001 _dbus_hash_table_remove_string (service->registry->service_hash,
1004 bus_service_unref (service);
1008 bus_service_relink (BusService *service,
1009 DBusPreallocatedHash *preallocated)
1011 _dbus_assert (service->owners == NULL);
1012 _dbus_assert (preallocated != NULL);
1014 _dbus_hash_table_insert_string_preallocated (service->registry->service_hash,
1019 bus_service_ref (service);
1023 * Data used to represent an ownership cancellation in
1024 * a bus transaction.
1028 BusOwner *owner; /**< the owner */
1029 BusService *service; /**< service to cancel ownership of */
1030 } OwnershipCancelData;
1033 cancel_ownership (void *data)
1035 OwnershipCancelData *d = data;
1037 /* We don't need to send messages notifying of these
1038 * changes, since we're reverting something that was
1039 * cancelled (effectively never really happened)
1041 bus_service_unlink_owner (d->service, d->owner);
1043 if (d->service->owners == NULL)
1044 bus_service_unlink (d->service);
1048 free_ownership_cancel_data (void *data)
1050 OwnershipCancelData *d = data;
1052 dbus_connection_unref (d->owner->conn);
1053 bus_owner_unref (d->owner);
1054 bus_service_unref (d->service);
1060 add_cancel_ownership_to_transaction (BusTransaction *transaction,
1061 BusService *service,
1064 OwnershipCancelData *d;
1066 d = dbus_new (OwnershipCancelData, 1);
1070 d->service = service;
1073 if (!bus_transaction_add_cancel_hook (transaction, cancel_ownership, d,
1074 free_ownership_cancel_data))
1080 bus_service_ref (d->service);
1081 bus_owner_ref (owner);
1082 dbus_connection_ref (d->owner->conn);
1087 /* this function is self-cancelling if you cancel the transaction */
1089 bus_service_add_owner (BusService *service,
1090 DBusConnection *connection,
1091 dbus_uint32_t flags,
1092 BusTransaction *transaction,
1095 BusOwner *bus_owner;
1096 DBusList *bus_owner_link;
1098 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1100 /* Send service acquired message first, OOM will result
1101 * in cancelling the transaction
1103 if (service->owners == NULL)
1105 if (!bus_driver_send_service_acquired (connection, service->name, transaction, error))
1109 bus_owner_link = _bus_service_find_owner_link (service, connection);
1111 if (bus_owner_link == NULL)
1113 bus_owner = bus_owner_new (service, connection, flags);
1114 if (bus_owner == NULL)
1116 BUS_SET_OOM (error);
1120 bus_owner_set_flags (bus_owner, flags);
1121 if (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) || service->owners == NULL)
1123 if (!_dbus_list_append (&service->owners,
1126 bus_owner_unref (bus_owner);
1127 BUS_SET_OOM (error);
1133 if (!_dbus_list_insert_after (&service->owners,
1134 _dbus_list_get_first_link (&service->owners),
1137 bus_owner_unref (bus_owner);
1138 BUS_SET_OOM (error);
1145 /* Update the link since we are already in the queue
1146 * No need for operations that can produce OOM
1149 bus_owner = (BusOwner *) bus_owner_link->data;
1150 if (flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
1153 _dbus_list_unlink (&service->owners, bus_owner_link);
1154 link = _dbus_list_get_first_link (&service->owners);
1155 _dbus_assert (link != NULL);
1157 _dbus_list_insert_after_link (&service->owners, link, bus_owner_link);
1160 bus_owner_set_flags (bus_owner, flags);
1164 if (!add_cancel_ownership_to_transaction (transaction,
1168 bus_service_unlink_owner (service, bus_owner);
1169 BUS_SET_OOM (error);
1179 BusService *service;
1180 BusOwner *before_owner; /* restore to position before this connection in owners list */
1181 DBusList *owner_link;
1182 DBusList *service_link;
1183 DBusPreallocatedHash *hash_entry;
1184 } OwnershipRestoreData;
1187 restore_ownership (void *data)
1189 OwnershipRestoreData *d = data;
1192 _dbus_assert (d->service_link != NULL);
1193 _dbus_assert (d->owner_link != NULL);
1195 if (d->service->owners == NULL)
1197 _dbus_assert (d->hash_entry != NULL);
1198 bus_service_relink (d->service, d->hash_entry);
1202 _dbus_assert (d->hash_entry == NULL);
1205 /* We don't need to send messages notifying of these
1206 * changes, since we're reverting something that was
1207 * cancelled (effectively never really happened)
1209 link = _dbus_list_get_first_link (&d->service->owners);
1210 while (link != NULL)
1212 if (link->data == d->before_owner)
1215 link = _dbus_list_get_next_link (&d->service->owners, link);
1218 _dbus_list_insert_before_link (&d->service->owners, link, d->owner_link);
1220 /* Note that removing then restoring this changes the order in which
1221 * ServiceDeleted messages are sent on destruction of the
1222 * connection. This should be OK as the only guarantee there is
1223 * that the base service is destroyed last, and we never even
1224 * tentatively remove the base service.
1226 bus_connection_add_owned_service_link (d->owner->conn, d->service_link);
1228 d->hash_entry = NULL;
1229 d->service_link = NULL;
1230 d->owner_link = NULL;
1234 free_ownership_restore_data (void *data)
1236 OwnershipRestoreData *d = data;
1238 if (d->service_link)
1239 _dbus_list_free_link (d->service_link);
1241 _dbus_list_free_link (d->owner_link);
1243 _dbus_hash_table_free_preallocated_entry (d->service->registry->service_hash,
1246 dbus_connection_unref (d->owner->conn);
1247 bus_owner_unref (d->owner);
1248 bus_service_unref (d->service);
1254 add_restore_ownership_to_transaction (BusTransaction *transaction,
1255 BusService *service,
1258 OwnershipRestoreData *d;
1261 d = dbus_new (OwnershipRestoreData, 1);
1265 d->service = service;
1267 d->service_link = _dbus_list_alloc_link (service);
1268 d->owner_link = _dbus_list_alloc_link (owner);
1269 d->hash_entry = _dbus_hash_table_preallocate_entry (service->registry->service_hash);
1271 bus_service_ref (d->service);
1272 bus_owner_ref (d->owner);
1273 dbus_connection_ref (d->owner->conn);
1275 d->before_owner = NULL;
1276 link = _dbus_list_get_first_link (&service->owners);
1277 while (link != NULL)
1279 if (link->data == owner)
1281 link = _dbus_list_get_next_link (&service->owners, link);
1284 d->before_owner = link->data;
1289 link = _dbus_list_get_next_link (&service->owners, link);
1292 if (d->service_link == NULL ||
1293 d->owner_link == NULL ||
1294 d->hash_entry == NULL ||
1295 !bus_transaction_add_cancel_hook (transaction, restore_ownership, d,
1296 free_ownership_restore_data))
1298 free_ownership_restore_data (d);
1306 bus_service_swap_owner (BusService *service,
1307 DBusConnection *connection,
1308 BusTransaction *transaction,
1311 DBusList *swap_link;
1312 BusOwner *primary_owner;
1314 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1316 /* We send out notifications before we do any work we
1317 * might have to undo if the notification-sending failed
1320 /* Send service lost message */
1321 primary_owner = bus_service_get_primary_owner (service);
1322 if (primary_owner == NULL || primary_owner->conn != connection)
1323 _dbus_assert_not_reached ("Tried to swap a non primary owner");
1326 if (!bus_driver_send_service_lost (connection, service->name,
1327 transaction, error))
1330 if (service->owners == NULL)
1332 _dbus_assert_not_reached ("Tried to swap owner of a service that has no owners");
1334 else if (_dbus_list_length_is_one (&service->owners))
1336 _dbus_assert_not_reached ("Tried to swap owner of a service that has no other owners in the queue");
1341 BusOwner *new_owner;
1342 DBusConnection *new_owner_conn;
1343 link = _dbus_list_get_first_link (&service->owners);
1344 _dbus_assert (link != NULL);
1345 link = _dbus_list_get_next_link (&service->owners, link);
1346 _dbus_assert (link != NULL);
1348 new_owner = (BusOwner *)link->data;
1349 new_owner_conn = new_owner->conn;
1351 if (!bus_driver_send_service_owner_changed (service->name,
1352 bus_connection_get_name (connection),
1353 bus_connection_get_name (new_owner_conn),
1354 transaction, error))
1357 /* This will be our new owner */
1358 if (!bus_driver_send_service_acquired (new_owner_conn,
1365 if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1367 BUS_SET_OOM (error);
1371 /* unlink the primary and make it the second link */
1372 swap_link = _dbus_list_get_first_link (&service->owners);
1373 _dbus_list_unlink (&service->owners, swap_link);
1375 _dbus_list_insert_after_link (&service->owners,
1376 _dbus_list_get_first_link (&service->owners),
1382 /* this function is self-cancelling if you cancel the transaction */
1384 bus_service_remove_owner (BusService *service,
1385 DBusConnection *connection,
1386 BusTransaction *transaction,
1389 BusOwner *primary_owner;
1391 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1393 /* We send out notifications before we do any work we
1394 * might have to undo if the notification-sending failed
1397 /* Send service lost message */
1398 primary_owner = bus_service_get_primary_owner (service);
1399 if (primary_owner != NULL && primary_owner->conn == connection)
1401 if (!bus_driver_send_service_lost (connection, service->name,
1402 transaction, error))
1407 /* if we are not the primary owner then just remove us from the queue */
1409 BusOwner *temp_owner;
1411 link = _bus_service_find_owner_link (service, connection);
1412 _dbus_list_unlink (&service->owners, link);
1413 temp_owner = (BusOwner *)link->data;
1414 bus_owner_unref (temp_owner);
1415 _dbus_list_free_link (link);
1420 if (service->owners == NULL)
1422 _dbus_assert_not_reached ("Tried to remove owner of a service that has no owners");
1424 else if (_dbus_list_length_is_one (&service->owners))
1426 if (!bus_driver_send_service_owner_changed (service->name,
1427 bus_connection_get_name (connection),
1429 transaction, error))
1435 BusOwner *new_owner;
1436 DBusConnection *new_owner_conn;
1437 link = _dbus_list_get_first_link (&service->owners);
1438 _dbus_assert (link != NULL);
1439 link = _dbus_list_get_next_link (&service->owners, link);
1440 _dbus_assert (link != NULL);
1442 new_owner = (BusOwner *)link->data;
1443 new_owner_conn = new_owner->conn;
1445 if (!bus_driver_send_service_owner_changed (service->name,
1446 bus_connection_get_name (connection),
1447 bus_connection_get_name (new_owner_conn),
1448 transaction, error))
1451 /* This will be our new owner */
1452 if (!bus_driver_send_service_acquired (new_owner_conn,
1459 if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1461 BUS_SET_OOM (error);
1465 bus_service_unlink_owner (service, primary_owner);
1467 if (service->owners == NULL)
1468 bus_service_unlink (service);
1474 bus_service_ref (BusService *service)
1476 _dbus_assert (service->refcount > 0);
1478 service->refcount += 1;
1484 bus_service_unref (BusService *service)
1486 _dbus_assert (service->refcount > 0);
1488 service->refcount -= 1;
1490 if (service->refcount == 0)
1492 _dbus_assert (service->owners == NULL);
1494 dbus_free (service->name);
1495 _dbus_mem_pool_dealloc (service->registry->service_pool, service);
1500 bus_service_get_primary_owners_connection (BusService *service)
1503 #ifdef ENABLE_KDBUS_TRANSPORT
1504 char unique_name[(unsigned int)(snprintf((char*)NULL, 0, "%llu", ULLONG_MAX) + sizeof(":1."))];
1507 owner = bus_service_get_primary_owner (service);
1509 #ifdef ENABLE_KDBUS_TRANSPORT
1512 if(bus_context_is_kdbus(service->registry->context))
1514 if(kdbus_get_name_owner(owner->conn, bus_service_get_name(service), unique_name) < 0)
1516 return _bus_service_find_owner_connection(service, unique_name); //bus_connections_find_conn_by_name would be safer? but slower
1529 bus_service_get_primary_owner (BusService *service)
1531 return _dbus_list_get_first (&service->owners);
1535 bus_service_get_name (BusService *service)
1537 return service->name;
1541 bus_service_get_allow_replacement (BusService *service)
1546 _dbus_assert (service->owners != NULL);
1548 link = _dbus_list_get_first_link (&service->owners);
1549 owner = (BusOwner *) link->data;
1551 return owner->allow_replacement;
1554 #ifdef ENABLE_KDBUS_TRANSPORT
1556 bus_service_get_is_kdbus_starter (BusService *service)
1561 _dbus_assert (service->owners != NULL);
1563 link = _dbus_list_get_first_link (&service->owners);
1564 owner = (BusOwner *) link->data;
1566 return owner->is_kdbus_starter;
1571 bus_service_has_owner (BusService *service,
1572 DBusConnection *connection)
1576 link = _bus_service_find_owner_link (service, connection);
1585 bus_service_list_queued_owners (BusService *service,
1586 DBusList **return_list,
1591 _dbus_assert (*return_list == NULL);
1593 link = _dbus_list_get_first_link (&service->owners);
1594 _dbus_assert (link != NULL);
1596 while (link != NULL)
1601 owner = (BusOwner *) link->data;
1602 uname = bus_connection_get_name (owner->conn);
1604 #ifdef ENABLE_KDBUS_TRANSPORT
1605 if(!owner->is_kdbus_starter)
1607 if (!_dbus_list_append (return_list, (char *)uname))
1610 link = _dbus_list_get_next_link (&service->owners, link);
1616 _dbus_list_clear (return_list);
1617 BUS_SET_OOM (error);