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)
714 if(_bus_service_find_owner_link (service, connection))
715 if (!bus_service_remove_owner (service, connection, transaction, error))
716 goto out; /* todo FIXME what to do with phantom connection? look into create_phantom_connection for a clue*/
720 activation = bus_context_get_activation (registry->context);
721 retval = bus_activation_send_pending_auto_activation_messages (activation,
731 bus_registry_release_service (BusRegistry *registry,
732 DBusConnection *connection,
733 const DBusString *service_name,
734 dbus_uint32_t *result,
735 BusTransaction *transaction,
743 if (!_dbus_validate_bus_name (service_name, 0,
744 _dbus_string_get_length (service_name)))
746 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
747 "Given bus name \"%s\" is not valid",
748 _dbus_string_get_const_data (service_name));
750 _dbus_verbose ("Attempt to release invalid service name\n");
755 if (_dbus_string_get_byte (service_name, 0) == ':')
757 /* Not allowed; the base service name cannot be created or released */
758 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
759 "Cannot release a service starting with ':' such as \"%s\"",
760 _dbus_string_get_const_data (service_name));
762 _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
763 _dbus_string_get_const_data (service_name));
768 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
770 /* Not allowed; the base service name cannot be created or released */
771 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
772 "Cannot release the %s service because it is owned by the bus",
775 _dbus_verbose ("Attempt to release service name \"%s\"",
781 if(bus_context_is_kdbus(bus_transaction_get_context (transaction))) //todo kdbus incl
785 sender_id = sender_name_to_id(dbus_message_get_sender((DBusMessage*)registry), error);
786 if(dbus_error_is_set(error))
789 *result = kdbus_release_name(connection, service_name, sender_id);
793 service = bus_registry_lookup (registry, service_name);
797 *result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
799 else if (!bus_service_has_owner (service, connection))
801 *result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
805 if (!bus_service_remove_owner (service, connection,
809 _dbus_assert (!bus_service_has_owner (service, connection));
810 *result = DBUS_RELEASE_NAME_REPLY_RELEASED;
821 bus_registry_set_service_context_table (BusRegistry *registry,
822 DBusHashTable *table)
824 DBusHashTable *new_table;
827 new_table = bus_selinux_id_table_new ();
831 _dbus_hash_iter_init (table, &iter);
832 while (_dbus_hash_iter_next (&iter))
834 const char *service = _dbus_hash_iter_get_string_key (&iter);
835 const char *context = _dbus_hash_iter_get_value (&iter);
837 if (!bus_selinux_id_table_insert (new_table,
843 if (registry->service_sid_table)
844 _dbus_hash_table_unref (registry->service_sid_table);
845 registry->service_sid_table = new_table;
850 bus_service_unlink_owner (BusService *service,
853 _dbus_list_remove_last (&service->owners, owner);
854 bus_owner_unref (owner);
858 bus_service_unlink (BusService *service)
860 _dbus_assert (service->owners == NULL);
862 /* the service may not be in the hash, if
863 * the failure causing transaction cancel
864 * was in the right place, but that's OK
866 _dbus_hash_table_remove_string (service->registry->service_hash,
869 bus_service_unref (service);
873 bus_service_relink (BusService *service,
874 DBusPreallocatedHash *preallocated)
876 _dbus_assert (service->owners == NULL);
877 _dbus_assert (preallocated != NULL);
879 _dbus_hash_table_insert_string_preallocated (service->registry->service_hash,
884 bus_service_ref (service);
888 * Data used to represent an ownership cancellation in
893 BusOwner *owner; /**< the owner */
894 BusService *service; /**< service to cancel ownership of */
895 } OwnershipCancelData;
898 cancel_ownership (void *data)
900 OwnershipCancelData *d = data;
902 /* We don't need to send messages notifying of these
903 * changes, since we're reverting something that was
904 * cancelled (effectively never really happened)
906 bus_service_unlink_owner (d->service, d->owner);
908 if (d->service->owners == NULL)
909 bus_service_unlink (d->service);
913 free_ownership_cancel_data (void *data)
915 OwnershipCancelData *d = data;
917 dbus_connection_unref (d->owner->conn);
918 bus_owner_unref (d->owner);
919 bus_service_unref (d->service);
925 add_cancel_ownership_to_transaction (BusTransaction *transaction,
929 OwnershipCancelData *d;
931 d = dbus_new (OwnershipCancelData, 1);
935 d->service = service;
938 if (!bus_transaction_add_cancel_hook (transaction, cancel_ownership, d,
939 free_ownership_cancel_data))
945 bus_service_ref (d->service);
946 bus_owner_ref (owner);
947 dbus_connection_ref (d->owner->conn);
952 /* this function is self-cancelling if you cancel the transaction */
954 bus_service_add_owner (BusService *service,
955 DBusConnection *connection,
957 BusTransaction *transaction,
961 DBusList *bus_owner_link;
963 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
965 /* Send service acquired message first, OOM will result
966 * in cancelling the transaction
968 if (service->owners == NULL)
970 if (!bus_driver_send_service_acquired (connection, service->name, transaction, error))
974 bus_owner_link = _bus_service_find_owner_link (service, connection);
976 if (bus_owner_link == NULL)
978 bus_owner = bus_owner_new (service, connection, flags);
979 if (bus_owner == NULL)
985 bus_owner_set_flags (bus_owner, flags);
986 if (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) || service->owners == NULL)
988 if (!_dbus_list_append (&service->owners,
991 bus_owner_unref (bus_owner);
998 if (!_dbus_list_insert_after (&service->owners,
999 _dbus_list_get_first_link (&service->owners),
1002 bus_owner_unref (bus_owner);
1003 BUS_SET_OOM (error);
1010 /* Update the link since we are already in the queue
1011 * No need for operations that can produce OOM
1014 bus_owner = (BusOwner *) bus_owner_link->data;
1015 if (flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
1018 _dbus_list_unlink (&service->owners, bus_owner_link);
1019 link = _dbus_list_get_first_link (&service->owners);
1020 _dbus_assert (link != NULL);
1022 _dbus_list_insert_after_link (&service->owners, link, bus_owner_link);
1025 bus_owner_set_flags (bus_owner, flags);
1029 if (!add_cancel_ownership_to_transaction (transaction,
1033 bus_service_unlink_owner (service, bus_owner);
1034 BUS_SET_OOM (error);
1044 BusService *service;
1045 BusOwner *before_owner; /* restore to position before this connection in owners list */
1046 DBusList *owner_link;
1047 DBusList *service_link;
1048 DBusPreallocatedHash *hash_entry;
1049 } OwnershipRestoreData;
1052 restore_ownership (void *data)
1054 OwnershipRestoreData *d = data;
1057 _dbus_assert (d->service_link != NULL);
1058 _dbus_assert (d->owner_link != NULL);
1060 if (d->service->owners == NULL)
1062 _dbus_assert (d->hash_entry != NULL);
1063 bus_service_relink (d->service, d->hash_entry);
1067 _dbus_assert (d->hash_entry == NULL);
1070 /* We don't need to send messages notifying of these
1071 * changes, since we're reverting something that was
1072 * cancelled (effectively never really happened)
1074 link = _dbus_list_get_first_link (&d->service->owners);
1075 while (link != NULL)
1077 if (link->data == d->before_owner)
1080 link = _dbus_list_get_next_link (&d->service->owners, link);
1083 _dbus_list_insert_before_link (&d->service->owners, link, d->owner_link);
1085 /* Note that removing then restoring this changes the order in which
1086 * ServiceDeleted messages are sent on destruction of the
1087 * connection. This should be OK as the only guarantee there is
1088 * that the base service is destroyed last, and we never even
1089 * tentatively remove the base service.
1091 bus_connection_add_owned_service_link (d->owner->conn, d->service_link);
1093 d->hash_entry = NULL;
1094 d->service_link = NULL;
1095 d->owner_link = NULL;
1099 free_ownership_restore_data (void *data)
1101 OwnershipRestoreData *d = data;
1103 if (d->service_link)
1104 _dbus_list_free_link (d->service_link);
1106 _dbus_list_free_link (d->owner_link);
1108 _dbus_hash_table_free_preallocated_entry (d->service->registry->service_hash,
1111 dbus_connection_unref (d->owner->conn);
1112 bus_owner_unref (d->owner);
1113 bus_service_unref (d->service);
1119 add_restore_ownership_to_transaction (BusTransaction *transaction,
1120 BusService *service,
1123 OwnershipRestoreData *d;
1126 d = dbus_new (OwnershipRestoreData, 1);
1130 d->service = service;
1132 d->service_link = _dbus_list_alloc_link (service);
1133 d->owner_link = _dbus_list_alloc_link (owner);
1134 d->hash_entry = _dbus_hash_table_preallocate_entry (service->registry->service_hash);
1136 bus_service_ref (d->service);
1137 bus_owner_ref (d->owner);
1138 dbus_connection_ref (d->owner->conn);
1140 d->before_owner = NULL;
1141 link = _dbus_list_get_first_link (&service->owners);
1142 while (link != NULL)
1144 if (link->data == owner)
1146 link = _dbus_list_get_next_link (&service->owners, link);
1149 d->before_owner = link->data;
1154 link = _dbus_list_get_next_link (&service->owners, link);
1157 if (d->service_link == NULL ||
1158 d->owner_link == NULL ||
1159 d->hash_entry == NULL ||
1160 !bus_transaction_add_cancel_hook (transaction, restore_ownership, d,
1161 free_ownership_restore_data))
1163 free_ownership_restore_data (d);
1171 bus_service_swap_owner (BusService *service,
1172 DBusConnection *connection,
1173 BusTransaction *transaction,
1176 DBusList *swap_link;
1177 BusOwner *primary_owner;
1179 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1181 /* We send out notifications before we do any work we
1182 * might have to undo if the notification-sending failed
1185 /* Send service lost message */
1186 primary_owner = bus_service_get_primary_owner (service);
1187 if (primary_owner == NULL || primary_owner->conn != connection)
1188 _dbus_assert_not_reached ("Tried to swap a non primary owner");
1191 if (!bus_driver_send_service_lost (connection, service->name,
1192 transaction, error))
1195 if (service->owners == NULL)
1197 _dbus_assert_not_reached ("Tried to swap owner of a service that has no owners");
1199 else if (_dbus_list_length_is_one (&service->owners))
1201 _dbus_assert_not_reached ("Tried to swap owner of a service that has no other owners in the queue");
1206 BusOwner *new_owner;
1207 DBusConnection *new_owner_conn;
1208 link = _dbus_list_get_first_link (&service->owners);
1209 _dbus_assert (link != NULL);
1210 link = _dbus_list_get_next_link (&service->owners, link);
1211 _dbus_assert (link != NULL);
1213 new_owner = (BusOwner *)link->data;
1214 new_owner_conn = new_owner->conn;
1216 if (!bus_driver_send_service_owner_changed (service->name,
1217 bus_connection_get_name (connection),
1218 bus_connection_get_name (new_owner_conn),
1219 transaction, error))
1222 /* This will be our new owner */
1223 if (!bus_driver_send_service_acquired (new_owner_conn,
1230 if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1232 BUS_SET_OOM (error);
1236 /* unlink the primary and make it the second link */
1237 swap_link = _dbus_list_get_first_link (&service->owners);
1238 _dbus_list_unlink (&service->owners, swap_link);
1240 _dbus_list_insert_after_link (&service->owners,
1241 _dbus_list_get_first_link (&service->owners),
1247 /* this function is self-cancelling if you cancel the transaction */
1249 bus_service_remove_owner (BusService *service,
1250 DBusConnection *connection,
1251 BusTransaction *transaction,
1254 BusOwner *primary_owner;
1256 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1258 /* We send out notifications before we do any work we
1259 * might have to undo if the notification-sending failed
1262 /* Send service lost message */
1263 primary_owner = bus_service_get_primary_owner (service);
1264 if (primary_owner != NULL && primary_owner->conn == connection)
1266 if (!bus_driver_send_service_lost (connection, service->name,
1267 transaction, error))
1272 /* if we are not the primary owner then just remove us from the queue */
1274 BusOwner *temp_owner;
1276 link = _bus_service_find_owner_link (service, connection);
1277 _dbus_list_unlink (&service->owners, link);
1278 temp_owner = (BusOwner *)link->data;
1279 bus_owner_unref (temp_owner);
1280 _dbus_list_free_link (link);
1285 if (service->owners == NULL)
1287 _dbus_assert_not_reached ("Tried to remove owner of a service that has no owners");
1289 else if (_dbus_list_length_is_one (&service->owners))
1291 if (!bus_driver_send_service_owner_changed (service->name,
1292 bus_connection_get_name (connection),
1294 transaction, error))
1300 BusOwner *new_owner;
1301 DBusConnection *new_owner_conn;
1302 link = _dbus_list_get_first_link (&service->owners);
1303 _dbus_assert (link != NULL);
1304 link = _dbus_list_get_next_link (&service->owners, link);
1305 _dbus_assert (link != NULL);
1307 new_owner = (BusOwner *)link->data;
1308 new_owner_conn = new_owner->conn;
1310 if (!bus_driver_send_service_owner_changed (service->name,
1311 bus_connection_get_name (connection),
1312 bus_connection_get_name (new_owner_conn),
1313 transaction, error))
1316 /* This will be our new owner */
1317 if (!bus_driver_send_service_acquired (new_owner_conn,
1324 if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1326 BUS_SET_OOM (error);
1330 bus_service_unlink_owner (service, primary_owner);
1332 if (service->owners == NULL)
1333 bus_service_unlink (service);
1339 bus_service_ref (BusService *service)
1341 _dbus_assert (service->refcount > 0);
1343 service->refcount += 1;
1349 bus_service_unref (BusService *service)
1351 _dbus_assert (service->refcount > 0);
1353 service->refcount -= 1;
1355 if (service->refcount == 0)
1357 _dbus_assert (service->owners == NULL);
1359 dbus_free (service->name);
1360 _dbus_mem_pool_dealloc (service->registry->service_pool, service);
1365 bus_service_get_primary_owners_connection (BusService *service)
1369 owner = bus_service_get_primary_owner (service);
1378 bus_service_get_primary_owner (BusService *service)
1380 return _dbus_list_get_first (&service->owners);
1384 bus_service_get_name (BusService *service)
1386 return service->name;
1390 bus_service_get_allow_replacement (BusService *service)
1395 _dbus_assert (service->owners != NULL);
1397 link = _dbus_list_get_first_link (&service->owners);
1398 owner = (BusOwner *) link->data;
1400 return owner->allow_replacement;
1404 bus_service_has_owner (BusService *service,
1405 DBusConnection *connection)
1409 link = _bus_service_find_owner_link (service, connection);
1418 bus_service_list_queued_owners (BusService *service,
1419 DBusList **return_list,
1424 _dbus_assert (*return_list == NULL);
1426 link = _dbus_list_get_first_link (&service->owners);
1427 _dbus_assert (link != NULL);
1429 while (link != NULL)
1434 owner = (BusOwner *) link->data;
1435 uname = bus_connection_get_name (owner->conn);
1437 if (!_dbus_list_append (return_list, (char *)uname))
1440 link = _dbus_list_get_next_link (&service->owners, link);
1446 _dbus_list_clear (return_list);
1447 BUS_SET_OOM (error);