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;
653 DBusString service_name_real;
654 const DBusString *service_name = &service_name_real;
658 const char* conn_unique_name;
659 DBusConnection* phantom;
661 if (!dbus_message_get_args (message, error,
662 DBUS_TYPE_STRING, &name,
663 DBUS_TYPE_UINT32, &flags,
669 _dbus_string_init_const (&service_name_real, name);
671 if (!_dbus_validate_bus_name (service_name, 0,
672 _dbus_string_get_length (service_name)))
674 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
675 "Requested bus name \"%s\" is not valid",
676 _dbus_string_get_const_data (service_name));
678 _dbus_verbose ("Attempt to acquire invalid service name\n");
683 if (_dbus_string_get_byte (service_name, 0) == ':')
685 /* Not allowed; only base services can start with ':' */
686 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
687 "Cannot acquire a service starting with ':' such as \"%s\"",
688 _dbus_string_get_const_data (service_name));
690 _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"",
691 _dbus_string_get_const_data (service_name));
696 conn_unique_name = dbus_message_get_sender(message);
698 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
700 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
701 "Connection \"%s\" is not allowed to own the service \"%s\"because "
702 "it is reserved for D-Bus' use only",
703 conn_unique_name, DBUS_SERVICE_DBUS);
707 sender_id = sender_name_to_id(conn_unique_name, error);
708 if(dbus_error_is_set(error))
711 phantom = bus_connections_find_conn_by_name(bus_connection_get_connections(connection), conn_unique_name);
714 phantom = create_phantom_connection(connection, conn_unique_name, error);
719 if (!bus_client_policy_check_can_own (bus_connection_get_policy (phantom), service_name))
721 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
722 "Connection \"%s\" is not allowed to own the service \"%s\" due "
723 "to security policies in the configuration file",
724 conn_unique_name, _dbus_string_get_const_data (service_name));
728 if(!kdbus_register_policy(service_name, phantom))
730 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
731 "Kdbus error when setting policy for connection \"%s\" and service name \"%s\"",
732 conn_unique_name, _dbus_string_get_const_data (service_name));
736 *result = kdbus_request_name(connection, service_name, flags, sender_id);
737 if(*result == -EPERM)
739 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
740 "Kdbus not allowed %s to own the service \"%s\"",
741 conn_unique_name, _dbus_string_get_const_data (service_name));
746 dbus_set_error (error, DBUS_ERROR_FAILED , "Name \"%s\" could not be acquired", name);
750 if((*result == DBUS_REQUEST_NAME_REPLY_IN_QUEUE) || (*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER))
752 service = bus_registry_lookup (registry, service_name);
755 service = bus_registry_ensure (registry, service_name, phantom, flags,
762 if (!bus_service_add_owner (service, phantom, flags, transaction, error))
766 activation = bus_context_get_activation (registry->context);
767 retval = bus_activation_send_pending_auto_activation_messages (activation,
778 kdbus_release_name(phantom, service_name, sender_id);
780 bus_connection_disconnected(phantom);
787 bus_registry_release_service (BusRegistry *registry,
788 DBusConnection *connection,
789 const DBusString *service_name,
790 dbus_uint32_t *result,
791 BusTransaction *transaction,
799 if (!_dbus_validate_bus_name (service_name, 0,
800 _dbus_string_get_length (service_name)))
802 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
803 "Given bus name \"%s\" is not valid",
804 _dbus_string_get_const_data (service_name));
806 _dbus_verbose ("Attempt to release invalid service name\n");
811 if (_dbus_string_get_byte (service_name, 0) == ':')
813 /* Not allowed; the base service name cannot be created or released */
814 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
815 "Cannot release a service starting with ':' such as \"%s\"",
816 _dbus_string_get_const_data (service_name));
818 _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
819 _dbus_string_get_const_data (service_name));
824 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
826 /* Not allowed; the base service name cannot be created or released */
827 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
828 "Cannot release the %s service because it is owned by the bus",
831 _dbus_verbose ("Attempt to release service name \"%s\"",
837 service = bus_registry_lookup (registry, service_name);
841 *result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
843 else if (!bus_service_has_owner (service, connection))
845 *result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
849 if (!bus_service_remove_owner (service, connection,
853 _dbus_assert (!bus_service_has_owner (service, connection));
854 *result = DBUS_RELEASE_NAME_REPLY_RELEASED;
863 #ifdef ENABLE_KDBUS_TRANSPORT
865 bus_registry_release_service_kdbus (const char* sender_name,
866 DBusConnection *connection,
867 const DBusString *service_name,
868 dbus_uint32_t *result,
869 BusTransaction *transaction,
872 dbus_bool_t retval = FALSE;
875 if (!_dbus_validate_bus_name (service_name, 0,
876 _dbus_string_get_length (service_name)))
878 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
879 "Given bus name \"%s\" is not valid",
880 _dbus_string_get_const_data (service_name));
882 _dbus_verbose ("Attempt to release invalid service name\n");
887 if (_dbus_string_get_byte (service_name, 0) == ':')
889 /* Not allowed; the base service name cannot be created or released */
890 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
891 "Cannot release a service starting with ':' such as \"%s\"",
892 _dbus_string_get_const_data (service_name));
894 _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
895 _dbus_string_get_const_data (service_name));
900 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
902 /* Not allowed; the base service name cannot be created or released */
903 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
904 "Cannot release the %s service because it is owned by the bus",
907 _dbus_verbose ("Attempt to release service name \"%s\"",
913 sender_id = sender_name_to_id(sender_name, error);
914 if(dbus_error_is_set(error))
917 *result = kdbus_release_name(connection, service_name, sender_id);
919 if(*result == DBUS_RELEASE_NAME_REPLY_RELEASED)
921 BusRegistry* registry;
924 registry = bus_connection_get_registry (connection);
925 service = bus_registry_lookup (registry, service_name);
928 DBusConnection* phantom;
930 phantom = _bus_service_find_owner_connection(service, sender_name);
933 bus_service_remove_owner (service, phantom, transaction, NULL);
934 /* todo we could remove phantom if he doesn't own any name
935 * to do this we should write function in connection.c to check if
936 * _dbus_list_get_last (&d->services_owned) returns not NULL
937 * or we can leave phantom - he will be removed when he disconnects from the bus
941 _dbus_verbose ("Didn't find phantom connection for released name!\n");
953 bus_registry_set_service_context_table (BusRegistry *registry,
954 DBusHashTable *table)
956 DBusHashTable *new_table;
959 new_table = bus_selinux_id_table_new ();
963 _dbus_hash_iter_init (table, &iter);
964 while (_dbus_hash_iter_next (&iter))
966 const char *service = _dbus_hash_iter_get_string_key (&iter);
967 const char *context = _dbus_hash_iter_get_value (&iter);
969 if (!bus_selinux_id_table_insert (new_table,
975 if (registry->service_sid_table)
976 _dbus_hash_table_unref (registry->service_sid_table);
977 registry->service_sid_table = new_table;
982 bus_service_unlink_owner (BusService *service,
985 _dbus_list_remove_last (&service->owners, owner);
986 bus_owner_unref (owner);
990 bus_service_unlink (BusService *service)
992 _dbus_assert (service->owners == NULL);
994 /* the service may not be in the hash, if
995 * the failure causing transaction cancel
996 * was in the right place, but that's OK
998 _dbus_hash_table_remove_string (service->registry->service_hash,
1001 bus_service_unref (service);
1005 bus_service_relink (BusService *service,
1006 DBusPreallocatedHash *preallocated)
1008 _dbus_assert (service->owners == NULL);
1009 _dbus_assert (preallocated != NULL);
1011 _dbus_hash_table_insert_string_preallocated (service->registry->service_hash,
1016 bus_service_ref (service);
1020 * Data used to represent an ownership cancellation in
1021 * a bus transaction.
1025 BusOwner *owner; /**< the owner */
1026 BusService *service; /**< service to cancel ownership of */
1027 } OwnershipCancelData;
1030 cancel_ownership (void *data)
1032 OwnershipCancelData *d = data;
1034 /* We don't need to send messages notifying of these
1035 * changes, since we're reverting something that was
1036 * cancelled (effectively never really happened)
1038 bus_service_unlink_owner (d->service, d->owner);
1040 if (d->service->owners == NULL)
1041 bus_service_unlink (d->service);
1045 free_ownership_cancel_data (void *data)
1047 OwnershipCancelData *d = data;
1049 dbus_connection_unref (d->owner->conn);
1050 bus_owner_unref (d->owner);
1051 bus_service_unref (d->service);
1057 add_cancel_ownership_to_transaction (BusTransaction *transaction,
1058 BusService *service,
1061 OwnershipCancelData *d;
1063 d = dbus_new (OwnershipCancelData, 1);
1067 d->service = service;
1070 if (!bus_transaction_add_cancel_hook (transaction, cancel_ownership, d,
1071 free_ownership_cancel_data))
1077 bus_service_ref (d->service);
1078 bus_owner_ref (owner);
1079 dbus_connection_ref (d->owner->conn);
1084 /* this function is self-cancelling if you cancel the transaction */
1086 bus_service_add_owner (BusService *service,
1087 DBusConnection *connection,
1088 dbus_uint32_t flags,
1089 BusTransaction *transaction,
1092 BusOwner *bus_owner;
1093 DBusList *bus_owner_link;
1095 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1097 /* Send service acquired message first, OOM will result
1098 * in cancelling the transaction
1100 if (service->owners == NULL)
1102 if (!bus_driver_send_service_acquired (connection, service->name, transaction, error))
1106 bus_owner_link = _bus_service_find_owner_link (service, connection);
1108 if (bus_owner_link == NULL)
1110 bus_owner = bus_owner_new (service, connection, flags);
1111 if (bus_owner == NULL)
1113 BUS_SET_OOM (error);
1117 bus_owner_set_flags (bus_owner, flags);
1118 if (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) || service->owners == NULL)
1120 if (!_dbus_list_append (&service->owners,
1123 bus_owner_unref (bus_owner);
1124 BUS_SET_OOM (error);
1130 if (!_dbus_list_insert_after (&service->owners,
1131 _dbus_list_get_first_link (&service->owners),
1134 bus_owner_unref (bus_owner);
1135 BUS_SET_OOM (error);
1142 /* Update the link since we are already in the queue
1143 * No need for operations that can produce OOM
1146 bus_owner = (BusOwner *) bus_owner_link->data;
1147 if (flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
1150 _dbus_list_unlink (&service->owners, bus_owner_link);
1151 link = _dbus_list_get_first_link (&service->owners);
1152 _dbus_assert (link != NULL);
1154 _dbus_list_insert_after_link (&service->owners, link, bus_owner_link);
1157 bus_owner_set_flags (bus_owner, flags);
1161 if (!add_cancel_ownership_to_transaction (transaction,
1165 bus_service_unlink_owner (service, bus_owner);
1166 BUS_SET_OOM (error);
1176 BusService *service;
1177 BusOwner *before_owner; /* restore to position before this connection in owners list */
1178 DBusList *owner_link;
1179 DBusList *service_link;
1180 DBusPreallocatedHash *hash_entry;
1181 } OwnershipRestoreData;
1184 restore_ownership (void *data)
1186 OwnershipRestoreData *d = data;
1189 _dbus_assert (d->service_link != NULL);
1190 _dbus_assert (d->owner_link != NULL);
1192 if (d->service->owners == NULL)
1194 _dbus_assert (d->hash_entry != NULL);
1195 bus_service_relink (d->service, d->hash_entry);
1199 _dbus_assert (d->hash_entry == NULL);
1202 /* We don't need to send messages notifying of these
1203 * changes, since we're reverting something that was
1204 * cancelled (effectively never really happened)
1206 link = _dbus_list_get_first_link (&d->service->owners);
1207 while (link != NULL)
1209 if (link->data == d->before_owner)
1212 link = _dbus_list_get_next_link (&d->service->owners, link);
1215 _dbus_list_insert_before_link (&d->service->owners, link, d->owner_link);
1217 /* Note that removing then restoring this changes the order in which
1218 * ServiceDeleted messages are sent on destruction of the
1219 * connection. This should be OK as the only guarantee there is
1220 * that the base service is destroyed last, and we never even
1221 * tentatively remove the base service.
1223 bus_connection_add_owned_service_link (d->owner->conn, d->service_link);
1225 d->hash_entry = NULL;
1226 d->service_link = NULL;
1227 d->owner_link = NULL;
1231 free_ownership_restore_data (void *data)
1233 OwnershipRestoreData *d = data;
1235 if (d->service_link)
1236 _dbus_list_free_link (d->service_link);
1238 _dbus_list_free_link (d->owner_link);
1240 _dbus_hash_table_free_preallocated_entry (d->service->registry->service_hash,
1243 dbus_connection_unref (d->owner->conn);
1244 bus_owner_unref (d->owner);
1245 bus_service_unref (d->service);
1251 add_restore_ownership_to_transaction (BusTransaction *transaction,
1252 BusService *service,
1255 OwnershipRestoreData *d;
1258 d = dbus_new (OwnershipRestoreData, 1);
1262 d->service = service;
1264 d->service_link = _dbus_list_alloc_link (service);
1265 d->owner_link = _dbus_list_alloc_link (owner);
1266 d->hash_entry = _dbus_hash_table_preallocate_entry (service->registry->service_hash);
1268 bus_service_ref (d->service);
1269 bus_owner_ref (d->owner);
1270 dbus_connection_ref (d->owner->conn);
1272 d->before_owner = NULL;
1273 link = _dbus_list_get_first_link (&service->owners);
1274 while (link != NULL)
1276 if (link->data == owner)
1278 link = _dbus_list_get_next_link (&service->owners, link);
1281 d->before_owner = link->data;
1286 link = _dbus_list_get_next_link (&service->owners, link);
1289 if (d->service_link == NULL ||
1290 d->owner_link == NULL ||
1291 d->hash_entry == NULL ||
1292 !bus_transaction_add_cancel_hook (transaction, restore_ownership, d,
1293 free_ownership_restore_data))
1295 free_ownership_restore_data (d);
1303 bus_service_swap_owner (BusService *service,
1304 DBusConnection *connection,
1305 BusTransaction *transaction,
1308 DBusList *swap_link;
1309 BusOwner *primary_owner;
1311 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1313 /* We send out notifications before we do any work we
1314 * might have to undo if the notification-sending failed
1317 /* Send service lost message */
1318 primary_owner = bus_service_get_primary_owner (service);
1319 if (primary_owner == NULL || primary_owner->conn != connection)
1320 _dbus_assert_not_reached ("Tried to swap a non primary owner");
1323 if (!bus_driver_send_service_lost (connection, service->name,
1324 transaction, error))
1327 if (service->owners == NULL)
1329 _dbus_assert_not_reached ("Tried to swap owner of a service that has no owners");
1331 else if (_dbus_list_length_is_one (&service->owners))
1333 _dbus_assert_not_reached ("Tried to swap owner of a service that has no other owners in the queue");
1338 BusOwner *new_owner;
1339 DBusConnection *new_owner_conn;
1340 link = _dbus_list_get_first_link (&service->owners);
1341 _dbus_assert (link != NULL);
1342 link = _dbus_list_get_next_link (&service->owners, link);
1343 _dbus_assert (link != NULL);
1345 new_owner = (BusOwner *)link->data;
1346 new_owner_conn = new_owner->conn;
1348 if (!bus_driver_send_service_owner_changed (service->name,
1349 bus_connection_get_name (connection),
1350 bus_connection_get_name (new_owner_conn),
1351 transaction, error))
1354 /* This will be our new owner */
1355 if (!bus_driver_send_service_acquired (new_owner_conn,
1362 if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1364 BUS_SET_OOM (error);
1368 /* unlink the primary and make it the second link */
1369 swap_link = _dbus_list_get_first_link (&service->owners);
1370 _dbus_list_unlink (&service->owners, swap_link);
1372 _dbus_list_insert_after_link (&service->owners,
1373 _dbus_list_get_first_link (&service->owners),
1379 /* this function is self-cancelling if you cancel the transaction */
1381 bus_service_remove_owner (BusService *service,
1382 DBusConnection *connection,
1383 BusTransaction *transaction,
1386 BusOwner *primary_owner;
1388 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1390 /* We send out notifications before we do any work we
1391 * might have to undo if the notification-sending failed
1394 /* Send service lost message */
1395 primary_owner = bus_service_get_primary_owner (service);
1396 if (primary_owner != NULL && primary_owner->conn == connection)
1398 if (!bus_driver_send_service_lost (connection, service->name,
1399 transaction, error))
1404 /* if we are not the primary owner then just remove us from the queue */
1406 BusOwner *temp_owner;
1408 link = _bus_service_find_owner_link (service, connection);
1409 _dbus_list_unlink (&service->owners, link);
1410 temp_owner = (BusOwner *)link->data;
1411 bus_owner_unref (temp_owner);
1412 _dbus_list_free_link (link);
1417 if (service->owners == NULL)
1419 _dbus_assert_not_reached ("Tried to remove owner of a service that has no owners");
1421 else if (_dbus_list_length_is_one (&service->owners))
1423 if (!bus_driver_send_service_owner_changed (service->name,
1424 bus_connection_get_name (connection),
1426 transaction, error))
1432 BusOwner *new_owner;
1433 DBusConnection *new_owner_conn;
1434 link = _dbus_list_get_first_link (&service->owners);
1435 _dbus_assert (link != NULL);
1436 link = _dbus_list_get_next_link (&service->owners, link);
1437 _dbus_assert (link != NULL);
1439 new_owner = (BusOwner *)link->data;
1440 new_owner_conn = new_owner->conn;
1442 if (!bus_driver_send_service_owner_changed (service->name,
1443 bus_connection_get_name (connection),
1444 bus_connection_get_name (new_owner_conn),
1445 transaction, error))
1448 /* This will be our new owner */
1449 if (!bus_driver_send_service_acquired (new_owner_conn,
1456 if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1458 BUS_SET_OOM (error);
1462 bus_service_unlink_owner (service, primary_owner);
1464 if (service->owners == NULL)
1465 bus_service_unlink (service);
1471 bus_service_ref (BusService *service)
1473 _dbus_assert (service->refcount > 0);
1475 service->refcount += 1;
1481 bus_service_unref (BusService *service)
1483 _dbus_assert (service->refcount > 0);
1485 service->refcount -= 1;
1487 if (service->refcount == 0)
1489 _dbus_assert (service->owners == NULL);
1491 dbus_free (service->name);
1492 _dbus_mem_pool_dealloc (service->registry->service_pool, service);
1497 bus_service_get_primary_owners_connection (BusService *service)
1500 #ifdef ENABLE_KDBUS_TRANSPORT
1501 char unique_name[(unsigned int)(snprintf((char*)NULL, 0, "%llu", ULLONG_MAX) + sizeof(":1."))];
1504 owner = bus_service_get_primary_owner (service);
1506 #ifdef ENABLE_KDBUS_TRANSPORT
1507 if(kdbus_get_name_owner(owner->conn, bus_service_get_name(service), unique_name) < 0)
1509 return _bus_service_find_owner_connection(service, unique_name); //bus_connections_find_conn_by_name would be safer? but slower
1519 bus_service_get_primary_owner (BusService *service)
1521 return _dbus_list_get_first (&service->owners);
1525 bus_service_get_name (BusService *service)
1527 return service->name;
1531 bus_service_get_allow_replacement (BusService *service)
1536 _dbus_assert (service->owners != NULL);
1538 link = _dbus_list_get_first_link (&service->owners);
1539 owner = (BusOwner *) link->data;
1541 return owner->allow_replacement;
1544 #ifdef ENABLE_KDBUS_TRANSPORT
1546 bus_service_get_is_kdbus_starter (BusService *service)
1551 _dbus_assert (service->owners != NULL);
1553 link = _dbus_list_get_first_link (&service->owners);
1554 owner = (BusOwner *) link->data;
1556 return owner->is_kdbus_starter;
1561 bus_service_has_owner (BusService *service,
1562 DBusConnection *connection)
1566 link = _bus_service_find_owner_link (service, connection);
1575 bus_service_list_queued_owners (BusService *service,
1576 DBusList **return_list,
1581 _dbus_assert (*return_list == NULL);
1583 link = _dbus_list_get_first_link (&service->owners);
1584 _dbus_assert (link != NULL);
1586 while (link != NULL)
1591 owner = (BusOwner *) link->data;
1592 uname = bus_connection_get_name (owner->conn);
1594 #ifdef ENABLE_KDBUS_TRANSPORT
1595 if(!owner->is_kdbus_starter)
1597 if (!_dbus_list_append (return_list, (char *)uname))
1600 link = _dbus_list_get_next_link (&service->owners, link);
1606 _dbus_list_clear (return_list);
1607 BUS_SET_OOM (error);