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
7 * Licensed under the Academic Free License version 2.1
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include <dbus/dbus-hash.h>
27 #include <dbus/dbus-list.h>
28 #include <dbus/dbus-mempool.h>
29 #include <dbus/dbus-marshal-validate.h>
30 #include <linux/types.h>
37 #include "connection.h"
39 #include "activation.h"
49 BusRegistry *registry;
61 unsigned int allow_replacement : 1;
62 unsigned int do_not_queue : 1;
71 DBusHashTable *service_hash;
72 DBusMemPool *service_pool;
73 DBusMemPool *owner_pool;
75 DBusHashTable *service_sid_table;
79 bus_registry_new (BusContext *context)
81 BusRegistry *registry;
83 registry = dbus_new0 (BusRegistry, 1);
87 registry->refcount = 1;
88 registry->context = context;
90 registry->service_hash = _dbus_hash_table_new (DBUS_HASH_STRING,
92 if (registry->service_hash == NULL)
95 registry->service_pool = _dbus_mem_pool_new (sizeof (BusService),
98 if (registry->service_pool == NULL)
101 registry->owner_pool = _dbus_mem_pool_new (sizeof (BusOwner),
104 if (registry->owner_pool == NULL)
107 registry->service_sid_table = NULL;
112 bus_registry_unref (registry);
117 bus_registry_ref (BusRegistry *registry)
119 _dbus_assert (registry->refcount > 0);
120 registry->refcount += 1;
126 bus_registry_unref (BusRegistry *registry)
128 _dbus_assert (registry->refcount > 0);
129 registry->refcount -= 1;
131 if (registry->refcount == 0)
133 if (registry->service_hash)
134 _dbus_hash_table_unref (registry->service_hash);
135 if (registry->service_pool)
136 _dbus_mem_pool_free (registry->service_pool);
137 if (registry->owner_pool)
138 _dbus_mem_pool_free (registry->owner_pool);
139 if (registry->service_sid_table)
140 _dbus_hash_table_unref (registry->service_sid_table);
142 dbus_free (registry);
147 bus_registry_lookup (BusRegistry *registry,
148 const DBusString *service_name)
152 service = _dbus_hash_table_lookup_string (registry->service_hash,
153 _dbus_string_get_const_data (service_name));
159 _bus_service_find_owner_link (BusService *service,
160 DBusConnection *connection)
164 link = _dbus_list_get_first_link (&service->owners);
170 bus_owner = (BusOwner *) link->data;
171 if (bus_owner->conn == connection)
174 link = _dbus_list_get_next_link (&service->owners, link);
180 static DBusConnection *
181 _bus_service_find_owner_connection (BusService *service,
182 const char* unique_name)
186 link = _dbus_list_get_first_link (&service->owners);
192 bus_owner = (BusOwner *) link->data;
193 if(!strcmp(bus_connection_get_name(bus_owner->conn), unique_name))
194 return bus_owner->conn;
196 link = _dbus_list_get_next_link (&service->owners, link);
203 bus_owner_set_flags (BusOwner *owner,
206 owner->allow_replacement =
207 (flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT) != FALSE;
209 owner->do_not_queue =
210 (flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) != FALSE;
214 bus_owner_new (BusService *service,
215 DBusConnection *conn,
220 result = _dbus_mem_pool_alloc (service->registry->owner_pool);
223 result->refcount = 1;
224 /* don't ref the connection because we don't want
225 to block the connection from going away.
226 transactions take care of reffing the connection
227 but we need to use refcounting on the owner
228 so that the owner does not get freed before
229 we can deref the connection in the transaction
232 result->service = service;
234 if (!bus_connection_add_owned_service (conn, service))
236 _dbus_mem_pool_dealloc (service->registry->owner_pool, result);
240 bus_owner_set_flags (result, flags);
246 bus_owner_ref (BusOwner *owner)
248 _dbus_assert (owner->refcount > 0);
249 owner->refcount += 1;
255 bus_owner_unref (BusOwner *owner)
257 _dbus_assert (owner->refcount > 0);
258 owner->refcount -= 1;
260 if (owner->refcount == 0)
262 bus_connection_remove_owned_service (owner->conn, owner->service);
263 _dbus_mem_pool_dealloc (owner->service->registry->owner_pool, owner);
268 bus_registry_ensure (BusRegistry *registry,
269 const DBusString *service_name,
270 DBusConnection *owner_connection_if_created,
272 BusTransaction *transaction,
277 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
279 _dbus_assert (owner_connection_if_created != NULL);
280 _dbus_assert (transaction != NULL);
282 service = _dbus_hash_table_lookup_string (registry->service_hash,
283 _dbus_string_get_const_data (service_name));
287 service = _dbus_mem_pool_alloc (registry->service_pool);
294 service->registry = registry;
295 service->refcount = 1;
297 _dbus_verbose ("copying string %p '%s' to service->name\n",
298 service_name, _dbus_string_get_const_data (service_name));
299 if (!_dbus_string_copy_data (service_name, &service->name))
301 _dbus_mem_pool_dealloc (registry->service_pool, service);
305 _dbus_verbose ("copied string %p '%s' to '%s'\n",
306 service_name, _dbus_string_get_const_data (service_name),
309 if (!bus_driver_send_service_owner_changed (service->name,
311 bus_connection_get_name (owner_connection_if_created),
314 bus_service_unref (service);
318 if (!bus_activation_service_created (bus_context_get_activation (registry->context),
319 service->name, transaction, error))
321 bus_service_unref (service);
325 if (!bus_service_add_owner (service, owner_connection_if_created, flags,
328 bus_service_unref (service);
332 if (!_dbus_hash_table_insert_string (registry->service_hash,
336 /* The add_owner gets reverted on transaction cancel */
345 bus_registry_foreach (BusRegistry *registry,
346 BusServiceForeachFunction function,
351 _dbus_hash_iter_init (registry->service_hash, &iter);
352 while (_dbus_hash_iter_next (&iter))
354 BusService *service = _dbus_hash_iter_get_value (&iter);
356 (* function) (service, data);
361 bus_registry_list_services (BusRegistry *registry,
369 len = _dbus_hash_table_get_n_entries (registry->service_hash);
370 retval = dbus_new (char *, len + 1);
375 _dbus_hash_iter_init (registry->service_hash, &iter);
377 while (_dbus_hash_iter_next (&iter))
379 BusService *service = _dbus_hash_iter_get_value (&iter);
381 retval[i] = _dbus_strdup (service->name);
382 if (retval[i] == NULL)
397 for (j = 0; j < i; j++)
398 dbus_free (retval[j]);
405 bus_registry_acquire_service (BusRegistry *registry,
406 DBusConnection *connection,
407 const DBusString *service_name,
409 dbus_uint32_t *result,
410 BusTransaction *transaction,
414 DBusConnection *old_owner_conn;
415 BusClientPolicy *policy;
417 BusActivation *activation;
419 BusOwner *primary_owner;
423 if (!_dbus_validate_bus_name (service_name, 0,
424 _dbus_string_get_length (service_name)))
426 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
427 "Requested bus name \"%s\" is not valid",
428 _dbus_string_get_const_data (service_name));
430 _dbus_verbose ("Attempt to acquire invalid service name\n");
435 if (_dbus_string_get_byte (service_name, 0) == ':')
437 /* Not allowed; only base services can start with ':' */
438 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
439 "Cannot acquire a service starting with ':' such as \"%s\"",
440 _dbus_string_get_const_data (service_name));
442 _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"",
443 _dbus_string_get_const_data (service_name));
448 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
450 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
451 "Connection \"%s\" is not allowed to own the service \"%s\"because "
452 "it is reserved for D-Bus' use only",
453 bus_connection_is_active (connection) ?
454 bus_connection_get_name (connection) :
460 policy = bus_connection_get_policy (connection);
461 _dbus_assert (policy != NULL);
463 /* Note that if sid is #NULL then the bus's own context gets used
464 * in bus_connection_selinux_allows_acquire_service()
466 sid = bus_selinux_id_table_lookup (registry->service_sid_table,
469 if (!bus_selinux_allows_acquire_service (connection, sid,
470 _dbus_string_get_const_data (service_name), error))
473 if (dbus_error_is_set (error) &&
474 dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY))
479 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
480 "Connection \"%s\" is not allowed to own the service \"%s\" due "
482 bus_connection_is_active (connection) ?
483 bus_connection_get_name (connection) :
485 _dbus_string_get_const_data (service_name));
489 if (!bus_client_policy_check_can_own (policy, service_name))
491 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
492 "Connection \"%s\" is not allowed to own the service \"%s\" due "
493 "to security policies in the configuration file",
494 bus_connection_is_active (connection) ?
495 bus_connection_get_name (connection) :
497 _dbus_string_get_const_data (service_name));
501 if (bus_connection_get_n_services_owned (connection) >=
502 bus_context_get_max_services_per_connection (registry->context))
504 dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
505 "Connection \"%s\" is not allowed to own more services "
506 "(increase limits in configuration file if required)",
507 bus_connection_is_active (connection) ?
508 bus_connection_get_name (connection) :
513 service = bus_registry_lookup (registry, service_name);
517 primary_owner = bus_service_get_primary_owner (service);
518 if (primary_owner != NULL)
519 old_owner_conn = primary_owner->conn;
521 old_owner_conn = NULL;
524 old_owner_conn = NULL;
528 service = bus_registry_ensure (registry,
529 service_name, connection, flags,
535 primary_owner = bus_service_get_primary_owner (service);
536 if (primary_owner == NULL)
539 if (old_owner_conn == NULL)
541 _dbus_assert (primary_owner->conn == connection);
543 *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
545 else if (old_owner_conn == connection)
547 bus_owner_set_flags (primary_owner, flags);
548 *result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
550 else if (((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
551 !(bus_service_get_allow_replacement (service))) ||
552 ((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
553 !(flags & DBUS_NAME_FLAG_REPLACE_EXISTING)))
556 BusOwner *temp_owner;
557 /* Since we can't be queued if we are already in the queue
560 link = _bus_service_find_owner_link (service, connection);
563 _dbus_list_unlink (&service->owners, link);
564 temp_owner = (BusOwner *)link->data;
565 bus_owner_unref (temp_owner);
566 _dbus_list_free_link (link);
569 *result = DBUS_REQUEST_NAME_REPLY_EXISTS;
571 else if (!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
572 (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) ||
573 !(bus_service_get_allow_replacement (service))))
575 /* Queue the connection */
576 if (!bus_service_add_owner (service, connection,
581 *result = DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
585 /* Replace the current owner */
587 /* We enqueue the new owner and remove the first one because
588 * that will cause NameAcquired and NameLost messages to
592 if (!bus_service_add_owner (service, connection,
597 if (primary_owner->do_not_queue)
599 if (!bus_service_remove_owner (service, old_owner_conn,
605 if (!bus_service_swap_owner (service, old_owner_conn,
611 _dbus_assert (connection == bus_service_get_primary_owner (service)->conn);
612 *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
615 activation = bus_context_get_activation (registry->context);
616 retval = bus_activation_send_pending_auto_activation_messages (activation,
626 bus_registry_acquire_kdbus_service (BusRegistry *registry,
627 DBusConnection *connection,
628 DBusMessage *message,
629 dbus_uint32_t *result,
630 BusTransaction *transaction,
635 BusActivation *activation;
637 DBusString service_name_real;
638 const DBusString *service_name = &service_name_real;
643 if (!dbus_message_get_args (message, error,
644 DBUS_TYPE_STRING, &name,
645 DBUS_TYPE_UINT32, &flags,
651 _dbus_string_init_const (&service_name_real, name);
653 if (!_dbus_validate_bus_name (service_name, 0,
654 _dbus_string_get_length (service_name)))
656 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
657 "Requested bus name \"%s\" is not valid",
658 _dbus_string_get_const_data (service_name));
660 _dbus_verbose ("Attempt to acquire invalid service name\n");
665 if (_dbus_string_get_byte (service_name, 0) == ':')
667 /* Not allowed; only base services can start with ':' */
668 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
669 "Cannot acquire a service starting with ':' such as \"%s\"",
670 _dbus_string_get_const_data (service_name));
672 _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"",
673 _dbus_string_get_const_data (service_name));
678 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
680 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
681 "Connection \"%s\" is not allowed to own the service \"%s\"because "
682 "it is reserved for D-Bus' use only",
683 bus_connection_is_active (connection) ?
684 bus_connection_get_name (connection) :
690 service = bus_registry_lookup (registry, service_name);
693 service = bus_registry_ensure (registry, service_name, connection, flags,
694 transaction, error); //adds daemon to service owners list - must be removed after right owner is set
698 if(!kdbus_register_policy(service_name, connection))
700 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
701 "Connection is not allowed to own the service \"%s\" due to security policies in the configuration file",
702 _dbus_string_get_const_data (service_name));
707 sender_id = sender_name_to_id(dbus_message_get_sender(message), error);
708 if(dbus_error_is_set(error))
711 *result = kdbus_request_name(connection, service_name, flags, sender_id);
712 if(*result == -EPERM)
714 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
715 "Connection is not allowed to own the service \"%s\" due to security policies in the configuration file",
716 _dbus_string_get_const_data (service_name));
721 dbus_set_error (error, DBUS_ERROR_FAILED , "Name \"%s\" could not be acquired", name);
725 if((*result == DBUS_REQUEST_NAME_REPLY_IN_QUEUE) || (*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER))
727 DBusConnection* phantom;
729 phantom = create_phantom_connection(connection, dbus_message_get_sender(message), error);
732 if (!bus_service_add_owner (service, phantom, flags, transaction, error))
734 dbus_connection_unref_phantom(phantom);
737 if(*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
739 /* Here we are removing DBus daemon as an owner of the service,
740 * which is set by bus_registry_ensure.
741 * If bus_service_remove_owner fail, we ignore it, because it has
742 * almost none impact on the usage
744 if(_bus_service_find_owner_link (service, connection))
745 bus_service_remove_owner (service, connection, transaction, NULL);
749 activation = bus_context_get_activation (registry->context);
750 retval = bus_activation_send_pending_auto_activation_messages (activation,
758 kdbus_release_name(connection, service_name, sender_id);
760 if(_bus_service_find_owner_link (service, connection))
761 bus_service_remove_owner (service, connection, transaction, NULL);
767 bus_registry_release_service (BusRegistry *registry,
768 DBusConnection *connection,
769 const DBusString *service_name,
770 dbus_uint32_t *result,
771 BusTransaction *transaction,
779 if (!_dbus_validate_bus_name (service_name, 0,
780 _dbus_string_get_length (service_name)))
782 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
783 "Given bus name \"%s\" is not valid",
784 _dbus_string_get_const_data (service_name));
786 _dbus_verbose ("Attempt to release invalid service name\n");
791 if (_dbus_string_get_byte (service_name, 0) == ':')
793 /* Not allowed; the base service name cannot be created or released */
794 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
795 "Cannot release a service starting with ':' such as \"%s\"",
796 _dbus_string_get_const_data (service_name));
798 _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
799 _dbus_string_get_const_data (service_name));
804 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
806 /* Not allowed; the base service name cannot be created or released */
807 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
808 "Cannot release the %s service because it is owned by the bus",
811 _dbus_verbose ("Attempt to release service name \"%s\"",
817 if(bus_context_is_kdbus(bus_transaction_get_context (transaction)))
821 sender_id = sender_name_to_id((const char*)registry, error);
822 if(dbus_error_is_set(error))
825 *result = kdbus_release_name(connection, service_name, sender_id);
827 if(*result == DBUS_RELEASE_NAME_REPLY_RELEASED)
831 name = (const char*)registry; //get name passed in registry pointer
832 registry = bus_connection_get_registry (connection); //than take original registry address
834 service = bus_registry_lookup (registry, service_name);
837 DBusConnection* phantom;
839 phantom = _bus_service_find_owner_connection(service, name);
842 bus_service_remove_owner (service, phantom, transaction, NULL);
843 dbus_connection_unref_phantom(phantom);
846 _dbus_verbose ("Didn't find phantom connection for released name!\n");
852 service = bus_registry_lookup (registry, service_name);
856 *result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
858 else if (!bus_service_has_owner (service, connection))
860 *result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
864 if (!bus_service_remove_owner (service, connection,
868 _dbus_assert (!bus_service_has_owner (service, connection));
869 *result = DBUS_RELEASE_NAME_REPLY_RELEASED;
880 bus_registry_set_service_context_table (BusRegistry *registry,
881 DBusHashTable *table)
883 DBusHashTable *new_table;
886 new_table = bus_selinux_id_table_new ();
890 _dbus_hash_iter_init (table, &iter);
891 while (_dbus_hash_iter_next (&iter))
893 const char *service = _dbus_hash_iter_get_string_key (&iter);
894 const char *context = _dbus_hash_iter_get_value (&iter);
896 if (!bus_selinux_id_table_insert (new_table,
902 if (registry->service_sid_table)
903 _dbus_hash_table_unref (registry->service_sid_table);
904 registry->service_sid_table = new_table;
909 bus_service_unlink_owner (BusService *service,
912 _dbus_list_remove_last (&service->owners, owner);
913 bus_owner_unref (owner);
917 bus_service_unlink (BusService *service)
919 _dbus_assert (service->owners == NULL);
921 /* the service may not be in the hash, if
922 * the failure causing transaction cancel
923 * was in the right place, but that's OK
925 _dbus_hash_table_remove_string (service->registry->service_hash,
928 bus_service_unref (service);
932 bus_service_relink (BusService *service,
933 DBusPreallocatedHash *preallocated)
935 _dbus_assert (service->owners == NULL);
936 _dbus_assert (preallocated != NULL);
938 _dbus_hash_table_insert_string_preallocated (service->registry->service_hash,
943 bus_service_ref (service);
947 * Data used to represent an ownership cancellation in
952 BusOwner *owner; /**< the owner */
953 BusService *service; /**< service to cancel ownership of */
954 } OwnershipCancelData;
957 cancel_ownership (void *data)
959 OwnershipCancelData *d = data;
961 /* We don't need to send messages notifying of these
962 * changes, since we're reverting something that was
963 * cancelled (effectively never really happened)
965 bus_service_unlink_owner (d->service, d->owner);
967 if (d->service->owners == NULL)
968 bus_service_unlink (d->service);
972 free_ownership_cancel_data (void *data)
974 OwnershipCancelData *d = data;
976 dbus_connection_unref (d->owner->conn);
977 bus_owner_unref (d->owner);
978 bus_service_unref (d->service);
984 add_cancel_ownership_to_transaction (BusTransaction *transaction,
988 OwnershipCancelData *d;
990 d = dbus_new (OwnershipCancelData, 1);
994 d->service = service;
997 if (!bus_transaction_add_cancel_hook (transaction, cancel_ownership, d,
998 free_ownership_cancel_data))
1004 bus_service_ref (d->service);
1005 bus_owner_ref (owner);
1006 dbus_connection_ref (d->owner->conn);
1011 /* this function is self-cancelling if you cancel the transaction */
1013 bus_service_add_owner (BusService *service,
1014 DBusConnection *connection,
1015 dbus_uint32_t flags,
1016 BusTransaction *transaction,
1019 BusOwner *bus_owner;
1020 DBusList *bus_owner_link;
1022 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1024 /* Send service acquired message first, OOM will result
1025 * in cancelling the transaction
1027 if (service->owners == NULL)
1029 if (!bus_driver_send_service_acquired (connection, service->name, transaction, error))
1033 bus_owner_link = _bus_service_find_owner_link (service, connection);
1035 if (bus_owner_link == NULL)
1037 bus_owner = bus_owner_new (service, connection, flags);
1038 if (bus_owner == NULL)
1040 BUS_SET_OOM (error);
1044 bus_owner_set_flags (bus_owner, flags);
1045 if (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) || service->owners == NULL)
1047 if (!_dbus_list_append (&service->owners,
1050 bus_owner_unref (bus_owner);
1051 BUS_SET_OOM (error);
1057 if (!_dbus_list_insert_after (&service->owners,
1058 _dbus_list_get_first_link (&service->owners),
1061 bus_owner_unref (bus_owner);
1062 BUS_SET_OOM (error);
1069 /* Update the link since we are already in the queue
1070 * No need for operations that can produce OOM
1073 bus_owner = (BusOwner *) bus_owner_link->data;
1074 if (flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
1077 _dbus_list_unlink (&service->owners, bus_owner_link);
1078 link = _dbus_list_get_first_link (&service->owners);
1079 _dbus_assert (link != NULL);
1081 _dbus_list_insert_after_link (&service->owners, link, bus_owner_link);
1084 bus_owner_set_flags (bus_owner, flags);
1088 if (!add_cancel_ownership_to_transaction (transaction,
1092 bus_service_unlink_owner (service, bus_owner);
1093 BUS_SET_OOM (error);
1103 BusService *service;
1104 BusOwner *before_owner; /* restore to position before this connection in owners list */
1105 DBusList *owner_link;
1106 DBusList *service_link;
1107 DBusPreallocatedHash *hash_entry;
1108 } OwnershipRestoreData;
1111 restore_ownership (void *data)
1113 OwnershipRestoreData *d = data;
1116 _dbus_assert (d->service_link != NULL);
1117 _dbus_assert (d->owner_link != NULL);
1119 if (d->service->owners == NULL)
1121 _dbus_assert (d->hash_entry != NULL);
1122 bus_service_relink (d->service, d->hash_entry);
1126 _dbus_assert (d->hash_entry == NULL);
1129 /* We don't need to send messages notifying of these
1130 * changes, since we're reverting something that was
1131 * cancelled (effectively never really happened)
1133 link = _dbus_list_get_first_link (&d->service->owners);
1134 while (link != NULL)
1136 if (link->data == d->before_owner)
1139 link = _dbus_list_get_next_link (&d->service->owners, link);
1142 _dbus_list_insert_before_link (&d->service->owners, link, d->owner_link);
1144 /* Note that removing then restoring this changes the order in which
1145 * ServiceDeleted messages are sent on destruction of the
1146 * connection. This should be OK as the only guarantee there is
1147 * that the base service is destroyed last, and we never even
1148 * tentatively remove the base service.
1150 bus_connection_add_owned_service_link (d->owner->conn, d->service_link);
1152 d->hash_entry = NULL;
1153 d->service_link = NULL;
1154 d->owner_link = NULL;
1158 free_ownership_restore_data (void *data)
1160 OwnershipRestoreData *d = data;
1162 if (d->service_link)
1163 _dbus_list_free_link (d->service_link);
1165 _dbus_list_free_link (d->owner_link);
1167 _dbus_hash_table_free_preallocated_entry (d->service->registry->service_hash,
1170 dbus_connection_unref (d->owner->conn);
1171 bus_owner_unref (d->owner);
1172 bus_service_unref (d->service);
1178 add_restore_ownership_to_transaction (BusTransaction *transaction,
1179 BusService *service,
1182 OwnershipRestoreData *d;
1185 d = dbus_new (OwnershipRestoreData, 1);
1189 d->service = service;
1191 d->service_link = _dbus_list_alloc_link (service);
1192 d->owner_link = _dbus_list_alloc_link (owner);
1193 d->hash_entry = _dbus_hash_table_preallocate_entry (service->registry->service_hash);
1195 bus_service_ref (d->service);
1196 bus_owner_ref (d->owner);
1197 dbus_connection_ref (d->owner->conn);
1199 d->before_owner = NULL;
1200 link = _dbus_list_get_first_link (&service->owners);
1201 while (link != NULL)
1203 if (link->data == owner)
1205 link = _dbus_list_get_next_link (&service->owners, link);
1208 d->before_owner = link->data;
1213 link = _dbus_list_get_next_link (&service->owners, link);
1216 if (d->service_link == NULL ||
1217 d->owner_link == NULL ||
1218 d->hash_entry == NULL ||
1219 !bus_transaction_add_cancel_hook (transaction, restore_ownership, d,
1220 free_ownership_restore_data))
1222 free_ownership_restore_data (d);
1230 bus_service_swap_owner (BusService *service,
1231 DBusConnection *connection,
1232 BusTransaction *transaction,
1235 DBusList *swap_link;
1236 BusOwner *primary_owner;
1238 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1240 /* We send out notifications before we do any work we
1241 * might have to undo if the notification-sending failed
1244 /* Send service lost message */
1245 primary_owner = bus_service_get_primary_owner (service);
1246 if (primary_owner == NULL || primary_owner->conn != connection)
1247 _dbus_assert_not_reached ("Tried to swap a non primary owner");
1250 if (!bus_driver_send_service_lost (connection, service->name,
1251 transaction, error))
1254 if (service->owners == NULL)
1256 _dbus_assert_not_reached ("Tried to swap owner of a service that has no owners");
1258 else if (_dbus_list_length_is_one (&service->owners))
1260 _dbus_assert_not_reached ("Tried to swap owner of a service that has no other owners in the queue");
1265 BusOwner *new_owner;
1266 DBusConnection *new_owner_conn;
1267 link = _dbus_list_get_first_link (&service->owners);
1268 _dbus_assert (link != NULL);
1269 link = _dbus_list_get_next_link (&service->owners, link);
1270 _dbus_assert (link != NULL);
1272 new_owner = (BusOwner *)link->data;
1273 new_owner_conn = new_owner->conn;
1275 if (!bus_driver_send_service_owner_changed (service->name,
1276 bus_connection_get_name (connection),
1277 bus_connection_get_name (new_owner_conn),
1278 transaction, error))
1281 /* This will be our new owner */
1282 if (!bus_driver_send_service_acquired (new_owner_conn,
1289 if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1291 BUS_SET_OOM (error);
1295 /* unlink the primary and make it the second link */
1296 swap_link = _dbus_list_get_first_link (&service->owners);
1297 _dbus_list_unlink (&service->owners, swap_link);
1299 _dbus_list_insert_after_link (&service->owners,
1300 _dbus_list_get_first_link (&service->owners),
1306 /* this function is self-cancelling if you cancel the transaction */
1308 bus_service_remove_owner (BusService *service,
1309 DBusConnection *connection,
1310 BusTransaction *transaction,
1313 BusOwner *primary_owner;
1315 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1317 /* We send out notifications before we do any work we
1318 * might have to undo if the notification-sending failed
1321 /* Send service lost message */
1322 primary_owner = bus_service_get_primary_owner (service);
1323 if (primary_owner != NULL && primary_owner->conn == connection)
1325 if (!bus_driver_send_service_lost (connection, service->name,
1326 transaction, error))
1331 /* if we are not the primary owner then just remove us from the queue */
1333 BusOwner *temp_owner;
1335 link = _bus_service_find_owner_link (service, connection);
1336 _dbus_list_unlink (&service->owners, link);
1337 temp_owner = (BusOwner *)link->data;
1338 bus_owner_unref (temp_owner);
1339 _dbus_list_free_link (link);
1344 if (service->owners == NULL)
1346 _dbus_assert_not_reached ("Tried to remove owner of a service that has no owners");
1348 else if (_dbus_list_length_is_one (&service->owners))
1350 if (!bus_driver_send_service_owner_changed (service->name,
1351 bus_connection_get_name (connection),
1353 transaction, error))
1359 BusOwner *new_owner;
1360 DBusConnection *new_owner_conn;
1361 link = _dbus_list_get_first_link (&service->owners);
1362 _dbus_assert (link != NULL);
1363 link = _dbus_list_get_next_link (&service->owners, link);
1364 _dbus_assert (link != NULL);
1366 new_owner = (BusOwner *)link->data;
1367 new_owner_conn = new_owner->conn;
1369 if (!bus_driver_send_service_owner_changed (service->name,
1370 bus_connection_get_name (connection),
1371 bus_connection_get_name (new_owner_conn),
1372 transaction, error))
1375 /* This will be our new owner */
1376 if (!bus_driver_send_service_acquired (new_owner_conn,
1383 if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1385 BUS_SET_OOM (error);
1389 bus_service_unlink_owner (service, primary_owner);
1391 if (service->owners == NULL)
1392 bus_service_unlink (service);
1398 bus_service_ref (BusService *service)
1400 _dbus_assert (service->refcount > 0);
1402 service->refcount += 1;
1408 bus_service_unref (BusService *service)
1410 _dbus_assert (service->refcount > 0);
1412 service->refcount -= 1;
1414 if (service->refcount == 0)
1416 _dbus_assert (service->owners == NULL);
1418 dbus_free (service->name);
1419 _dbus_mem_pool_dealloc (service->registry->service_pool, service);
1424 bus_service_get_primary_owners_connection (BusService *service)
1428 owner = bus_service_get_primary_owner (service);
1437 bus_service_get_primary_owner (BusService *service)
1439 return _dbus_list_get_first (&service->owners);
1443 bus_service_get_name (BusService *service)
1445 return service->name;
1449 bus_service_get_allow_replacement (BusService *service)
1454 _dbus_assert (service->owners != NULL);
1456 link = _dbus_list_get_first_link (&service->owners);
1457 owner = (BusOwner *) link->data;
1459 return owner->allow_replacement;
1463 bus_service_has_owner (BusService *service,
1464 DBusConnection *connection)
1468 link = _bus_service_find_owner_link (service, connection);
1477 bus_service_list_queued_owners (BusService *service,
1478 DBusList **return_list,
1483 _dbus_assert (*return_list == NULL);
1485 link = _dbus_list_get_first_link (&service->owners);
1486 _dbus_assert (link != NULL);
1488 while (link != NULL)
1493 owner = (BusOwner *) link->data;
1494 uname = bus_connection_get_name (owner->conn);
1496 if (!_dbus_list_append (return_list, (char *)uname))
1499 link = _dbus_list_get_next_link (&service->owners, link);
1505 _dbus_list_clear (return_list);
1506 BUS_SET_OOM (error);