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);
181 bus_owner_set_flags (BusOwner *owner,
184 owner->allow_replacement =
185 (flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT) != FALSE;
187 owner->do_not_queue =
188 (flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) != FALSE;
192 bus_owner_new (BusService *service,
193 DBusConnection *conn,
198 result = _dbus_mem_pool_alloc (service->registry->owner_pool);
201 result->refcount = 1;
202 /* don't ref the connection because we don't want
203 to block the connection from going away.
204 transactions take care of reffing the connection
205 but we need to use refcounting on the owner
206 so that the owner does not get freed before
207 we can deref the connection in the transaction
210 result->service = service;
212 if (!bus_connection_add_owned_service (conn, service))
214 _dbus_mem_pool_dealloc (service->registry->owner_pool, result);
218 bus_owner_set_flags (result, flags);
224 bus_owner_ref (BusOwner *owner)
226 _dbus_assert (owner->refcount > 0);
227 owner->refcount += 1;
233 bus_owner_unref (BusOwner *owner)
235 _dbus_assert (owner->refcount > 0);
236 owner->refcount -= 1;
238 if (owner->refcount == 0)
240 bus_connection_remove_owned_service (owner->conn, owner->service);
241 _dbus_mem_pool_dealloc (owner->service->registry->owner_pool, owner);
246 bus_registry_ensure (BusRegistry *registry,
247 const DBusString *service_name,
248 DBusConnection *owner_connection_if_created,
250 BusTransaction *transaction,
255 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
257 _dbus_assert (owner_connection_if_created != NULL);
258 _dbus_assert (transaction != NULL);
260 service = _dbus_hash_table_lookup_string (registry->service_hash,
261 _dbus_string_get_const_data (service_name));
265 service = _dbus_mem_pool_alloc (registry->service_pool);
272 service->registry = registry;
273 service->refcount = 1;
275 _dbus_verbose ("copying string %p '%s' to service->name\n",
276 service_name, _dbus_string_get_const_data (service_name));
277 if (!_dbus_string_copy_data (service_name, &service->name))
279 _dbus_mem_pool_dealloc (registry->service_pool, service);
283 _dbus_verbose ("copied string %p '%s' to '%s'\n",
284 service_name, _dbus_string_get_const_data (service_name),
287 if (!bus_driver_send_service_owner_changed (service->name,
289 bus_connection_get_name (owner_connection_if_created),
292 bus_service_unref (service);
296 if (!bus_activation_service_created (bus_context_get_activation (registry->context),
297 service->name, transaction, error))
299 bus_service_unref (service);
303 if (!bus_service_add_owner (service, owner_connection_if_created, flags,
306 bus_service_unref (service);
310 if (!_dbus_hash_table_insert_string (registry->service_hash,
314 /* The add_owner gets reverted on transaction cancel */
323 bus_registry_foreach (BusRegistry *registry,
324 BusServiceForeachFunction function,
329 _dbus_hash_iter_init (registry->service_hash, &iter);
330 while (_dbus_hash_iter_next (&iter))
332 BusService *service = _dbus_hash_iter_get_value (&iter);
334 (* function) (service, data);
339 bus_registry_list_services (BusRegistry *registry,
347 len = _dbus_hash_table_get_n_entries (registry->service_hash);
348 retval = dbus_new (char *, len + 1);
353 _dbus_hash_iter_init (registry->service_hash, &iter);
355 while (_dbus_hash_iter_next (&iter))
357 BusService *service = _dbus_hash_iter_get_value (&iter);
359 retval[i] = _dbus_strdup (service->name);
360 if (retval[i] == NULL)
375 for (j = 0; j < i; j++)
376 dbus_free (retval[j]);
383 bus_registry_acquire_service (BusRegistry *registry,
384 DBusConnection *connection,
385 const DBusString *service_name,
387 dbus_uint32_t *result,
388 BusTransaction *transaction,
392 DBusConnection *old_owner_conn;
393 BusClientPolicy *policy;
395 BusActivation *activation;
397 BusOwner *primary_owner;
401 if (!_dbus_validate_bus_name (service_name, 0,
402 _dbus_string_get_length (service_name)))
404 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
405 "Requested bus name \"%s\" is not valid",
406 _dbus_string_get_const_data (service_name));
408 _dbus_verbose ("Attempt to acquire invalid service name\n");
413 if (_dbus_string_get_byte (service_name, 0) == ':')
415 /* Not allowed; only base services can start with ':' */
416 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
417 "Cannot acquire a service starting with ':' such as \"%s\"",
418 _dbus_string_get_const_data (service_name));
420 _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"",
421 _dbus_string_get_const_data (service_name));
426 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
428 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
429 "Connection \"%s\" is not allowed to own the service \"%s\"because "
430 "it is reserved for D-Bus' use only",
431 bus_connection_is_active (connection) ?
432 bus_connection_get_name (connection) :
438 policy = bus_connection_get_policy (connection);
439 _dbus_assert (policy != NULL);
441 /* Note that if sid is #NULL then the bus's own context gets used
442 * in bus_connection_selinux_allows_acquire_service()
444 sid = bus_selinux_id_table_lookup (registry->service_sid_table,
447 if (!bus_selinux_allows_acquire_service (connection, sid,
448 _dbus_string_get_const_data (service_name), error))
451 if (dbus_error_is_set (error) &&
452 dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY))
457 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
458 "Connection \"%s\" is not allowed to own the service \"%s\" due "
460 bus_connection_is_active (connection) ?
461 bus_connection_get_name (connection) :
463 _dbus_string_get_const_data (service_name));
467 if (!bus_client_policy_check_can_own (policy, service_name))
469 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
470 "Connection \"%s\" is not allowed to own the service \"%s\" due "
471 "to security policies in the configuration file",
472 bus_connection_is_active (connection) ?
473 bus_connection_get_name (connection) :
475 _dbus_string_get_const_data (service_name));
479 if (bus_connection_get_n_services_owned (connection) >=
480 bus_context_get_max_services_per_connection (registry->context))
482 dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
483 "Connection \"%s\" is not allowed to own more services "
484 "(increase limits in configuration file if required)",
485 bus_connection_is_active (connection) ?
486 bus_connection_get_name (connection) :
491 service = bus_registry_lookup (registry, service_name);
495 primary_owner = bus_service_get_primary_owner (service);
496 if (primary_owner != NULL)
497 old_owner_conn = primary_owner->conn;
499 old_owner_conn = NULL;
502 old_owner_conn = NULL;
506 service = bus_registry_ensure (registry,
507 service_name, connection, flags,
513 primary_owner = bus_service_get_primary_owner (service);
514 if (primary_owner == NULL)
517 if (old_owner_conn == NULL)
519 _dbus_assert (primary_owner->conn == connection);
521 *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
523 else if (old_owner_conn == connection)
525 bus_owner_set_flags (primary_owner, flags);
526 *result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
528 else if (((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
529 !(bus_service_get_allow_replacement (service))) ||
530 ((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
531 !(flags & DBUS_NAME_FLAG_REPLACE_EXISTING)))
534 BusOwner *temp_owner;
535 /* Since we can't be queued if we are already in the queue
538 link = _bus_service_find_owner_link (service, connection);
541 _dbus_list_unlink (&service->owners, link);
542 temp_owner = (BusOwner *)link->data;
543 bus_owner_unref (temp_owner);
544 _dbus_list_free_link (link);
547 *result = DBUS_REQUEST_NAME_REPLY_EXISTS;
549 else if (!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
550 (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) ||
551 !(bus_service_get_allow_replacement (service))))
553 /* Queue the connection */
554 if (!bus_service_add_owner (service, connection,
559 *result = DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
563 /* Replace the current owner */
565 /* We enqueue the new owner and remove the first one because
566 * that will cause NameAcquired and NameLost messages to
570 if (!bus_service_add_owner (service, connection,
575 if (primary_owner->do_not_queue)
577 if (!bus_service_remove_owner (service, old_owner_conn,
583 if (!bus_service_swap_owner (service, old_owner_conn,
589 _dbus_assert (connection == bus_service_get_primary_owner (service)->conn);
590 *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
593 activation = bus_context_get_activation (registry->context);
594 retval = bus_activation_send_pending_auto_activation_messages (activation,
604 bus_registry_acquire_kdbus_service (BusRegistry *registry,
605 DBusConnection *connection,
606 DBusMessage *message,
607 dbus_uint32_t *result,
608 BusTransaction *transaction,
613 BusActivation *activation;
615 DBusString service_name_real;
616 const DBusString *service_name = &service_name_real;
621 if (!dbus_message_get_args (message, error,
622 DBUS_TYPE_STRING, &name,
623 DBUS_TYPE_UINT32, &flags,
629 _dbus_string_init_const (&service_name_real, name);
631 if (!_dbus_validate_bus_name (service_name, 0,
632 _dbus_string_get_length (service_name)))
634 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
635 "Requested bus name \"%s\" is not valid",
636 _dbus_string_get_const_data (service_name));
638 _dbus_verbose ("Attempt to acquire invalid service name\n");
643 if (_dbus_string_get_byte (service_name, 0) == ':')
645 /* Not allowed; only base services can start with ':' */
646 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
647 "Cannot acquire a service starting with ':' such as \"%s\"",
648 _dbus_string_get_const_data (service_name));
650 _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"",
651 _dbus_string_get_const_data (service_name));
656 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
658 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
659 "Connection \"%s\" is not allowed to own the service \"%s\"because "
660 "it is reserved for D-Bus' use only",
661 bus_connection_is_active (connection) ?
662 bus_connection_get_name (connection) :
668 service = bus_registry_lookup (registry, service_name);
671 service = bus_registry_ensure (registry, service_name, connection, flags,
672 transaction, error); //adds daemon to service owners list - must be removed after right owner is set
676 if(!kdbus_register_policy(service_name, connection))
678 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
679 "Connection is not allowed to own the service \"%s\" due to security policies in the configuration file",
680 _dbus_string_get_const_data (service_name));
685 sender_id = sender_name_to_id(dbus_message_get_sender(message), error);
686 if(dbus_error_is_set(error))
689 *result = kdbus_request_name(connection, service_name, flags, sender_id);
690 if(*result == -EPERM)
692 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
693 "Connection is not allowed to own the service \"%s\" due to security policies in the configuration file",
694 _dbus_string_get_const_data (service_name));
699 dbus_set_error (error, DBUS_ERROR_FAILED , "Name \"%s\" could not be acquired", name);
703 if((*result == DBUS_REQUEST_NAME_REPLY_IN_QUEUE) || (*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER))
705 DBusConnection* phantom;
707 phantom = create_phantom_connection(connection, dbus_message_get_sender(message));
710 if (!bus_service_add_owner (service, phantom, flags, transaction, error))
711 goto out; /* todo FIXME what to do with phantom connection? look into create_phantom_connection for a clue*/
712 if(*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
713 if (!bus_service_remove_owner (service, connection, transaction, error))
714 goto out; /* todo FIXME what to do with phantom connection? look into create_phantom_connection for a clue*/
717 activation = bus_context_get_activation (registry->context);
718 retval = bus_activation_send_pending_auto_activation_messages (activation,
728 bus_registry_release_service (BusRegistry *registry,
729 DBusConnection *connection,
730 const DBusString *service_name,
731 dbus_uint32_t *result,
732 BusTransaction *transaction,
740 if (!_dbus_validate_bus_name (service_name, 0,
741 _dbus_string_get_length (service_name)))
743 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
744 "Given bus name \"%s\" is not valid",
745 _dbus_string_get_const_data (service_name));
747 _dbus_verbose ("Attempt to release invalid service name\n");
752 if (_dbus_string_get_byte (service_name, 0) == ':')
754 /* Not allowed; the base service name cannot be created or released */
755 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
756 "Cannot release a service starting with ':' such as \"%s\"",
757 _dbus_string_get_const_data (service_name));
759 _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
760 _dbus_string_get_const_data (service_name));
765 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
767 /* Not allowed; the base service name cannot be created or released */
768 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
769 "Cannot release the %s service because it is owned by the bus",
772 _dbus_verbose ("Attempt to release service name \"%s\"",
778 if(bus_context_is_kdbus(bus_transaction_get_context (transaction))) //todo kdbus incl
782 sender_id = sender_name_to_id(dbus_message_get_sender((DBusMessage*)registry), error);
783 if(dbus_error_is_set(error))
786 *result = kdbus_release_name(connection, service_name, sender_id);
790 service = bus_registry_lookup (registry, service_name);
794 *result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
796 else if (!bus_service_has_owner (service, connection))
798 *result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
802 if (!bus_service_remove_owner (service, connection,
806 _dbus_assert (!bus_service_has_owner (service, connection));
807 *result = DBUS_RELEASE_NAME_REPLY_RELEASED;
818 bus_registry_set_service_context_table (BusRegistry *registry,
819 DBusHashTable *table)
821 DBusHashTable *new_table;
824 new_table = bus_selinux_id_table_new ();
828 _dbus_hash_iter_init (table, &iter);
829 while (_dbus_hash_iter_next (&iter))
831 const char *service = _dbus_hash_iter_get_string_key (&iter);
832 const char *context = _dbus_hash_iter_get_value (&iter);
834 if (!bus_selinux_id_table_insert (new_table,
840 if (registry->service_sid_table)
841 _dbus_hash_table_unref (registry->service_sid_table);
842 registry->service_sid_table = new_table;
847 bus_service_unlink_owner (BusService *service,
850 _dbus_list_remove_last (&service->owners, owner);
851 bus_owner_unref (owner);
855 bus_service_unlink (BusService *service)
857 _dbus_assert (service->owners == NULL);
859 /* the service may not be in the hash, if
860 * the failure causing transaction cancel
861 * was in the right place, but that's OK
863 _dbus_hash_table_remove_string (service->registry->service_hash,
866 bus_service_unref (service);
870 bus_service_relink (BusService *service,
871 DBusPreallocatedHash *preallocated)
873 _dbus_assert (service->owners == NULL);
874 _dbus_assert (preallocated != NULL);
876 _dbus_hash_table_insert_string_preallocated (service->registry->service_hash,
881 bus_service_ref (service);
885 * Data used to represent an ownership cancellation in
890 BusOwner *owner; /**< the owner */
891 BusService *service; /**< service to cancel ownership of */
892 } OwnershipCancelData;
895 cancel_ownership (void *data)
897 OwnershipCancelData *d = data;
899 /* We don't need to send messages notifying of these
900 * changes, since we're reverting something that was
901 * cancelled (effectively never really happened)
903 bus_service_unlink_owner (d->service, d->owner);
905 if (d->service->owners == NULL)
906 bus_service_unlink (d->service);
910 free_ownership_cancel_data (void *data)
912 OwnershipCancelData *d = data;
914 dbus_connection_unref (d->owner->conn);
915 bus_owner_unref (d->owner);
916 bus_service_unref (d->service);
922 add_cancel_ownership_to_transaction (BusTransaction *transaction,
926 OwnershipCancelData *d;
928 d = dbus_new (OwnershipCancelData, 1);
932 d->service = service;
935 if (!bus_transaction_add_cancel_hook (transaction, cancel_ownership, d,
936 free_ownership_cancel_data))
942 bus_service_ref (d->service);
943 bus_owner_ref (owner);
944 dbus_connection_ref (d->owner->conn);
949 /* this function is self-cancelling if you cancel the transaction */
951 bus_service_add_owner (BusService *service,
952 DBusConnection *connection,
954 BusTransaction *transaction,
958 DBusList *bus_owner_link;
960 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
962 /* Send service acquired message first, OOM will result
963 * in cancelling the transaction
965 if (service->owners == NULL)
967 if (!bus_driver_send_service_acquired (connection, service->name, transaction, error))
971 bus_owner_link = _bus_service_find_owner_link (service, connection);
973 if (bus_owner_link == NULL)
975 bus_owner = bus_owner_new (service, connection, flags);
976 if (bus_owner == NULL)
982 bus_owner_set_flags (bus_owner, flags);
983 if (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) || service->owners == NULL)
985 if (!_dbus_list_append (&service->owners,
988 bus_owner_unref (bus_owner);
995 if (!_dbus_list_insert_after (&service->owners,
996 _dbus_list_get_first_link (&service->owners),
999 bus_owner_unref (bus_owner);
1000 BUS_SET_OOM (error);
1007 /* Update the link since we are already in the queue
1008 * No need for operations that can produce OOM
1011 bus_owner = (BusOwner *) bus_owner_link->data;
1012 if (flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
1015 _dbus_list_unlink (&service->owners, bus_owner_link);
1016 link = _dbus_list_get_first_link (&service->owners);
1017 _dbus_assert (link != NULL);
1019 _dbus_list_insert_after_link (&service->owners, link, bus_owner_link);
1022 bus_owner_set_flags (bus_owner, flags);
1026 if (!add_cancel_ownership_to_transaction (transaction,
1030 bus_service_unlink_owner (service, bus_owner);
1031 BUS_SET_OOM (error);
1041 BusService *service;
1042 BusOwner *before_owner; /* restore to position before this connection in owners list */
1043 DBusList *owner_link;
1044 DBusList *service_link;
1045 DBusPreallocatedHash *hash_entry;
1046 } OwnershipRestoreData;
1049 restore_ownership (void *data)
1051 OwnershipRestoreData *d = data;
1054 _dbus_assert (d->service_link != NULL);
1055 _dbus_assert (d->owner_link != NULL);
1057 if (d->service->owners == NULL)
1059 _dbus_assert (d->hash_entry != NULL);
1060 bus_service_relink (d->service, d->hash_entry);
1064 _dbus_assert (d->hash_entry == NULL);
1067 /* We don't need to send messages notifying of these
1068 * changes, since we're reverting something that was
1069 * cancelled (effectively never really happened)
1071 link = _dbus_list_get_first_link (&d->service->owners);
1072 while (link != NULL)
1074 if (link->data == d->before_owner)
1077 link = _dbus_list_get_next_link (&d->service->owners, link);
1080 _dbus_list_insert_before_link (&d->service->owners, link, d->owner_link);
1082 /* Note that removing then restoring this changes the order in which
1083 * ServiceDeleted messages are sent on destruction of the
1084 * connection. This should be OK as the only guarantee there is
1085 * that the base service is destroyed last, and we never even
1086 * tentatively remove the base service.
1088 bus_connection_add_owned_service_link (d->owner->conn, d->service_link);
1090 d->hash_entry = NULL;
1091 d->service_link = NULL;
1092 d->owner_link = NULL;
1096 free_ownership_restore_data (void *data)
1098 OwnershipRestoreData *d = data;
1100 if (d->service_link)
1101 _dbus_list_free_link (d->service_link);
1103 _dbus_list_free_link (d->owner_link);
1105 _dbus_hash_table_free_preallocated_entry (d->service->registry->service_hash,
1108 dbus_connection_unref (d->owner->conn);
1109 bus_owner_unref (d->owner);
1110 bus_service_unref (d->service);
1116 add_restore_ownership_to_transaction (BusTransaction *transaction,
1117 BusService *service,
1120 OwnershipRestoreData *d;
1123 d = dbus_new (OwnershipRestoreData, 1);
1127 d->service = service;
1129 d->service_link = _dbus_list_alloc_link (service);
1130 d->owner_link = _dbus_list_alloc_link (owner);
1131 d->hash_entry = _dbus_hash_table_preallocate_entry (service->registry->service_hash);
1133 bus_service_ref (d->service);
1134 bus_owner_ref (d->owner);
1135 dbus_connection_ref (d->owner->conn);
1137 d->before_owner = NULL;
1138 link = _dbus_list_get_first_link (&service->owners);
1139 while (link != NULL)
1141 if (link->data == owner)
1143 link = _dbus_list_get_next_link (&service->owners, link);
1146 d->before_owner = link->data;
1151 link = _dbus_list_get_next_link (&service->owners, link);
1154 if (d->service_link == NULL ||
1155 d->owner_link == NULL ||
1156 d->hash_entry == NULL ||
1157 !bus_transaction_add_cancel_hook (transaction, restore_ownership, d,
1158 free_ownership_restore_data))
1160 free_ownership_restore_data (d);
1168 bus_service_swap_owner (BusService *service,
1169 DBusConnection *connection,
1170 BusTransaction *transaction,
1173 DBusList *swap_link;
1174 BusOwner *primary_owner;
1176 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1178 /* We send out notifications before we do any work we
1179 * might have to undo if the notification-sending failed
1182 /* Send service lost message */
1183 primary_owner = bus_service_get_primary_owner (service);
1184 if (primary_owner == NULL || primary_owner->conn != connection)
1185 _dbus_assert_not_reached ("Tried to swap a non primary owner");
1188 if (!bus_driver_send_service_lost (connection, service->name,
1189 transaction, error))
1192 if (service->owners == NULL)
1194 _dbus_assert_not_reached ("Tried to swap owner of a service that has no owners");
1196 else if (_dbus_list_length_is_one (&service->owners))
1198 _dbus_assert_not_reached ("Tried to swap owner of a service that has no other owners in the queue");
1203 BusOwner *new_owner;
1204 DBusConnection *new_owner_conn;
1205 link = _dbus_list_get_first_link (&service->owners);
1206 _dbus_assert (link != NULL);
1207 link = _dbus_list_get_next_link (&service->owners, link);
1208 _dbus_assert (link != NULL);
1210 new_owner = (BusOwner *)link->data;
1211 new_owner_conn = new_owner->conn;
1213 if (!bus_driver_send_service_owner_changed (service->name,
1214 bus_connection_get_name (connection),
1215 bus_connection_get_name (new_owner_conn),
1216 transaction, error))
1219 /* This will be our new owner */
1220 if (!bus_driver_send_service_acquired (new_owner_conn,
1227 if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1229 BUS_SET_OOM (error);
1233 /* unlink the primary and make it the second link */
1234 swap_link = _dbus_list_get_first_link (&service->owners);
1235 _dbus_list_unlink (&service->owners, swap_link);
1237 _dbus_list_insert_after_link (&service->owners,
1238 _dbus_list_get_first_link (&service->owners),
1244 /* this function is self-cancelling if you cancel the transaction */
1246 bus_service_remove_owner (BusService *service,
1247 DBusConnection *connection,
1248 BusTransaction *transaction,
1251 BusOwner *primary_owner;
1253 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1255 /* We send out notifications before we do any work we
1256 * might have to undo if the notification-sending failed
1259 /* Send service lost message */
1260 primary_owner = bus_service_get_primary_owner (service);
1261 if (primary_owner != NULL && primary_owner->conn == connection)
1263 if (!bus_driver_send_service_lost (connection, service->name,
1264 transaction, error))
1269 /* if we are not the primary owner then just remove us from the queue */
1271 BusOwner *temp_owner;
1273 link = _bus_service_find_owner_link (service, connection);
1274 _dbus_list_unlink (&service->owners, link);
1275 temp_owner = (BusOwner *)link->data;
1276 bus_owner_unref (temp_owner);
1277 _dbus_list_free_link (link);
1282 if (service->owners == NULL)
1284 _dbus_assert_not_reached ("Tried to remove owner of a service that has no owners");
1286 else if (_dbus_list_length_is_one (&service->owners))
1288 if (!bus_driver_send_service_owner_changed (service->name,
1289 bus_connection_get_name (connection),
1291 transaction, error))
1297 BusOwner *new_owner;
1298 DBusConnection *new_owner_conn;
1299 link = _dbus_list_get_first_link (&service->owners);
1300 _dbus_assert (link != NULL);
1301 link = _dbus_list_get_next_link (&service->owners, link);
1302 _dbus_assert (link != NULL);
1304 new_owner = (BusOwner *)link->data;
1305 new_owner_conn = new_owner->conn;
1307 if (!bus_driver_send_service_owner_changed (service->name,
1308 bus_connection_get_name (connection),
1309 bus_connection_get_name (new_owner_conn),
1310 transaction, error))
1313 /* This will be our new owner */
1314 if (!bus_driver_send_service_acquired (new_owner_conn,
1321 if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1323 BUS_SET_OOM (error);
1327 bus_service_unlink_owner (service, primary_owner);
1329 if (service->owners == NULL)
1330 bus_service_unlink (service);
1336 bus_service_ref (BusService *service)
1338 _dbus_assert (service->refcount > 0);
1340 service->refcount += 1;
1346 bus_service_unref (BusService *service)
1348 _dbus_assert (service->refcount > 0);
1350 service->refcount -= 1;
1352 if (service->refcount == 0)
1354 _dbus_assert (service->owners == NULL);
1356 dbus_free (service->name);
1357 _dbus_mem_pool_dealloc (service->registry->service_pool, service);
1362 bus_service_get_primary_owners_connection (BusService *service)
1366 owner = bus_service_get_primary_owner (service);
1375 bus_service_get_primary_owner (BusService *service)
1377 return _dbus_list_get_first (&service->owners);
1381 bus_service_get_name (BusService *service)
1383 return service->name;
1387 bus_service_get_allow_replacement (BusService *service)
1392 _dbus_assert (service->owners != NULL);
1394 link = _dbus_list_get_first_link (&service->owners);
1395 owner = (BusOwner *) link->data;
1397 return owner->allow_replacement;
1401 bus_service_has_owner (BusService *service,
1402 DBusConnection *connection)
1406 link = _bus_service_find_owner_link (service, connection);
1415 bus_service_list_queued_owners (BusService *service,
1416 DBusList **return_list,
1421 _dbus_assert (*return_list == NULL);
1423 link = _dbus_list_get_first_link (&service->owners);
1424 _dbus_assert (link != NULL);
1426 while (link != NULL)
1431 owner = (BusOwner *) link->data;
1432 uname = bus_connection_get_name (owner->conn);
1434 if (!_dbus_list_append (return_list, (char *)uname))
1437 link = _dbus_list_get_next_link (&service->owners, link);
1443 _dbus_list_clear (return_list);
1444 BUS_SET_OOM (error);