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;
730 name = dbus_message_get_sender(message);
731 phantom = bus_connections_find_conn_by_name(bus_connection_get_connections(connection), name);
733 phantom = create_phantom_connection(connection, name, error);
736 if (!bus_service_add_owner (service, phantom, flags, transaction, error))
738 if(*result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
740 /* Here we are removing DBus daemon as an owner of the service,
741 * which is set by bus_registry_ensure.
742 * If bus_service_remove_owner fail, we ignore it, because it has
743 * almost none impact on the usage
745 if(_bus_service_find_owner_link (service, connection))
746 bus_service_remove_owner (service, connection, transaction, NULL);
750 activation = bus_context_get_activation (registry->context);
751 retval = bus_activation_send_pending_auto_activation_messages (activation,
759 kdbus_release_name(connection, service_name, sender_id);
761 if(_bus_service_find_owner_link (service, connection))
762 bus_service_remove_owner (service, connection, transaction, NULL);
768 bus_registry_release_service (BusRegistry *registry,
769 DBusConnection *connection,
770 const DBusString *service_name,
771 dbus_uint32_t *result,
772 BusTransaction *transaction,
780 if (!_dbus_validate_bus_name (service_name, 0,
781 _dbus_string_get_length (service_name)))
783 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
784 "Given bus name \"%s\" is not valid",
785 _dbus_string_get_const_data (service_name));
787 _dbus_verbose ("Attempt to release invalid service name\n");
792 if (_dbus_string_get_byte (service_name, 0) == ':')
794 /* Not allowed; the base service name cannot be created or released */
795 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
796 "Cannot release a service starting with ':' such as \"%s\"",
797 _dbus_string_get_const_data (service_name));
799 _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
800 _dbus_string_get_const_data (service_name));
805 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
807 /* Not allowed; the base service name cannot be created or released */
808 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
809 "Cannot release the %s service because it is owned by the bus",
812 _dbus_verbose ("Attempt to release service name \"%s\"",
818 service = bus_registry_lookup (registry, service_name);
822 *result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
824 else if (!bus_service_has_owner (service, connection))
826 *result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
830 if (!bus_service_remove_owner (service, connection,
834 _dbus_assert (!bus_service_has_owner (service, connection));
835 *result = DBUS_RELEASE_NAME_REPLY_RELEASED;
845 bus_registry_release_service_kdbus (const char* sender_name,
846 DBusConnection *connection,
847 const DBusString *service_name,
848 dbus_uint32_t *result,
849 BusTransaction *transaction,
852 dbus_bool_t retval = FALSE;
855 if (!_dbus_validate_bus_name (service_name, 0,
856 _dbus_string_get_length (service_name)))
858 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
859 "Given bus name \"%s\" is not valid",
860 _dbus_string_get_const_data (service_name));
862 _dbus_verbose ("Attempt to release invalid service name\n");
867 if (_dbus_string_get_byte (service_name, 0) == ':')
869 /* Not allowed; the base service name cannot be created or released */
870 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
871 "Cannot release a service starting with ':' such as \"%s\"",
872 _dbus_string_get_const_data (service_name));
874 _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
875 _dbus_string_get_const_data (service_name));
880 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
882 /* Not allowed; the base service name cannot be created or released */
883 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
884 "Cannot release the %s service because it is owned by the bus",
887 _dbus_verbose ("Attempt to release service name \"%s\"",
893 sender_id = sender_name_to_id(sender_name, error);
894 if(dbus_error_is_set(error))
897 *result = kdbus_release_name(connection, service_name, sender_id);
899 if(*result == DBUS_RELEASE_NAME_REPLY_RELEASED)
901 BusRegistry* registry;
904 registry = bus_connection_get_registry (connection);
905 service = bus_registry_lookup (registry, service_name);
908 DBusConnection* phantom;
910 phantom = _bus_service_find_owner_connection(service, sender_name);
913 bus_service_remove_owner (service, phantom, transaction, NULL);
914 /* todo we could remove phantom if he doesn't own any name
915 * to do this we should write function in connection.c to check if
916 * _dbus_list_get_last (&d->services_owned) returns not NULL
917 * or we can leave phantom - he will be removed when he disconnects from the bus
921 _dbus_verbose ("Didn't find phantom connection for released name!\n");
932 bus_registry_set_service_context_table (BusRegistry *registry,
933 DBusHashTable *table)
935 DBusHashTable *new_table;
938 new_table = bus_selinux_id_table_new ();
942 _dbus_hash_iter_init (table, &iter);
943 while (_dbus_hash_iter_next (&iter))
945 const char *service = _dbus_hash_iter_get_string_key (&iter);
946 const char *context = _dbus_hash_iter_get_value (&iter);
948 if (!bus_selinux_id_table_insert (new_table,
954 if (registry->service_sid_table)
955 _dbus_hash_table_unref (registry->service_sid_table);
956 registry->service_sid_table = new_table;
961 bus_service_unlink_owner (BusService *service,
964 _dbus_list_remove_last (&service->owners, owner);
965 bus_owner_unref (owner);
969 bus_service_unlink (BusService *service)
971 _dbus_assert (service->owners == NULL);
973 /* the service may not be in the hash, if
974 * the failure causing transaction cancel
975 * was in the right place, but that's OK
977 _dbus_hash_table_remove_string (service->registry->service_hash,
980 bus_service_unref (service);
984 bus_service_relink (BusService *service,
985 DBusPreallocatedHash *preallocated)
987 _dbus_assert (service->owners == NULL);
988 _dbus_assert (preallocated != NULL);
990 _dbus_hash_table_insert_string_preallocated (service->registry->service_hash,
995 bus_service_ref (service);
999 * Data used to represent an ownership cancellation in
1000 * a bus transaction.
1004 BusOwner *owner; /**< the owner */
1005 BusService *service; /**< service to cancel ownership of */
1006 } OwnershipCancelData;
1009 cancel_ownership (void *data)
1011 OwnershipCancelData *d = data;
1013 /* We don't need to send messages notifying of these
1014 * changes, since we're reverting something that was
1015 * cancelled (effectively never really happened)
1017 bus_service_unlink_owner (d->service, d->owner);
1019 if (d->service->owners == NULL)
1020 bus_service_unlink (d->service);
1024 free_ownership_cancel_data (void *data)
1026 OwnershipCancelData *d = data;
1028 dbus_connection_unref (d->owner->conn);
1029 bus_owner_unref (d->owner);
1030 bus_service_unref (d->service);
1036 add_cancel_ownership_to_transaction (BusTransaction *transaction,
1037 BusService *service,
1040 OwnershipCancelData *d;
1042 d = dbus_new (OwnershipCancelData, 1);
1046 d->service = service;
1049 if (!bus_transaction_add_cancel_hook (transaction, cancel_ownership, d,
1050 free_ownership_cancel_data))
1056 bus_service_ref (d->service);
1057 bus_owner_ref (owner);
1058 dbus_connection_ref (d->owner->conn);
1063 /* this function is self-cancelling if you cancel the transaction */
1065 bus_service_add_owner (BusService *service,
1066 DBusConnection *connection,
1067 dbus_uint32_t flags,
1068 BusTransaction *transaction,
1071 BusOwner *bus_owner;
1072 DBusList *bus_owner_link;
1074 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1076 /* Send service acquired message first, OOM will result
1077 * in cancelling the transaction
1079 if (service->owners == NULL)
1081 if (!bus_driver_send_service_acquired (connection, service->name, transaction, error))
1085 bus_owner_link = _bus_service_find_owner_link (service, connection);
1087 if (bus_owner_link == NULL)
1089 bus_owner = bus_owner_new (service, connection, flags);
1090 if (bus_owner == NULL)
1092 BUS_SET_OOM (error);
1096 bus_owner_set_flags (bus_owner, flags);
1097 if (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) || service->owners == NULL)
1099 if (!_dbus_list_append (&service->owners,
1102 bus_owner_unref (bus_owner);
1103 BUS_SET_OOM (error);
1109 if (!_dbus_list_insert_after (&service->owners,
1110 _dbus_list_get_first_link (&service->owners),
1113 bus_owner_unref (bus_owner);
1114 BUS_SET_OOM (error);
1121 /* Update the link since we are already in the queue
1122 * No need for operations that can produce OOM
1125 bus_owner = (BusOwner *) bus_owner_link->data;
1126 if (flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
1129 _dbus_list_unlink (&service->owners, bus_owner_link);
1130 link = _dbus_list_get_first_link (&service->owners);
1131 _dbus_assert (link != NULL);
1133 _dbus_list_insert_after_link (&service->owners, link, bus_owner_link);
1136 bus_owner_set_flags (bus_owner, flags);
1140 if (!add_cancel_ownership_to_transaction (transaction,
1144 bus_service_unlink_owner (service, bus_owner);
1145 BUS_SET_OOM (error);
1155 BusService *service;
1156 BusOwner *before_owner; /* restore to position before this connection in owners list */
1157 DBusList *owner_link;
1158 DBusList *service_link;
1159 DBusPreallocatedHash *hash_entry;
1160 } OwnershipRestoreData;
1163 restore_ownership (void *data)
1165 OwnershipRestoreData *d = data;
1168 _dbus_assert (d->service_link != NULL);
1169 _dbus_assert (d->owner_link != NULL);
1171 if (d->service->owners == NULL)
1173 _dbus_assert (d->hash_entry != NULL);
1174 bus_service_relink (d->service, d->hash_entry);
1178 _dbus_assert (d->hash_entry == NULL);
1181 /* We don't need to send messages notifying of these
1182 * changes, since we're reverting something that was
1183 * cancelled (effectively never really happened)
1185 link = _dbus_list_get_first_link (&d->service->owners);
1186 while (link != NULL)
1188 if (link->data == d->before_owner)
1191 link = _dbus_list_get_next_link (&d->service->owners, link);
1194 _dbus_list_insert_before_link (&d->service->owners, link, d->owner_link);
1196 /* Note that removing then restoring this changes the order in which
1197 * ServiceDeleted messages are sent on destruction of the
1198 * connection. This should be OK as the only guarantee there is
1199 * that the base service is destroyed last, and we never even
1200 * tentatively remove the base service.
1202 bus_connection_add_owned_service_link (d->owner->conn, d->service_link);
1204 d->hash_entry = NULL;
1205 d->service_link = NULL;
1206 d->owner_link = NULL;
1210 free_ownership_restore_data (void *data)
1212 OwnershipRestoreData *d = data;
1214 if (d->service_link)
1215 _dbus_list_free_link (d->service_link);
1217 _dbus_list_free_link (d->owner_link);
1219 _dbus_hash_table_free_preallocated_entry (d->service->registry->service_hash,
1222 dbus_connection_unref (d->owner->conn);
1223 bus_owner_unref (d->owner);
1224 bus_service_unref (d->service);
1230 add_restore_ownership_to_transaction (BusTransaction *transaction,
1231 BusService *service,
1234 OwnershipRestoreData *d;
1237 d = dbus_new (OwnershipRestoreData, 1);
1241 d->service = service;
1243 d->service_link = _dbus_list_alloc_link (service);
1244 d->owner_link = _dbus_list_alloc_link (owner);
1245 d->hash_entry = _dbus_hash_table_preallocate_entry (service->registry->service_hash);
1247 bus_service_ref (d->service);
1248 bus_owner_ref (d->owner);
1249 dbus_connection_ref (d->owner->conn);
1251 d->before_owner = NULL;
1252 link = _dbus_list_get_first_link (&service->owners);
1253 while (link != NULL)
1255 if (link->data == owner)
1257 link = _dbus_list_get_next_link (&service->owners, link);
1260 d->before_owner = link->data;
1265 link = _dbus_list_get_next_link (&service->owners, link);
1268 if (d->service_link == NULL ||
1269 d->owner_link == NULL ||
1270 d->hash_entry == NULL ||
1271 !bus_transaction_add_cancel_hook (transaction, restore_ownership, d,
1272 free_ownership_restore_data))
1274 free_ownership_restore_data (d);
1282 bus_service_swap_owner (BusService *service,
1283 DBusConnection *connection,
1284 BusTransaction *transaction,
1287 DBusList *swap_link;
1288 BusOwner *primary_owner;
1290 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1292 /* We send out notifications before we do any work we
1293 * might have to undo if the notification-sending failed
1296 /* Send service lost message */
1297 primary_owner = bus_service_get_primary_owner (service);
1298 if (primary_owner == NULL || primary_owner->conn != connection)
1299 _dbus_assert_not_reached ("Tried to swap a non primary owner");
1302 if (!bus_driver_send_service_lost (connection, service->name,
1303 transaction, error))
1306 if (service->owners == NULL)
1308 _dbus_assert_not_reached ("Tried to swap owner of a service that has no owners");
1310 else if (_dbus_list_length_is_one (&service->owners))
1312 _dbus_assert_not_reached ("Tried to swap owner of a service that has no other owners in the queue");
1317 BusOwner *new_owner;
1318 DBusConnection *new_owner_conn;
1319 link = _dbus_list_get_first_link (&service->owners);
1320 _dbus_assert (link != NULL);
1321 link = _dbus_list_get_next_link (&service->owners, link);
1322 _dbus_assert (link != NULL);
1324 new_owner = (BusOwner *)link->data;
1325 new_owner_conn = new_owner->conn;
1327 if (!bus_driver_send_service_owner_changed (service->name,
1328 bus_connection_get_name (connection),
1329 bus_connection_get_name (new_owner_conn),
1330 transaction, error))
1333 /* This will be our new owner */
1334 if (!bus_driver_send_service_acquired (new_owner_conn,
1341 if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1343 BUS_SET_OOM (error);
1347 /* unlink the primary and make it the second link */
1348 swap_link = _dbus_list_get_first_link (&service->owners);
1349 _dbus_list_unlink (&service->owners, swap_link);
1351 _dbus_list_insert_after_link (&service->owners,
1352 _dbus_list_get_first_link (&service->owners),
1358 /* this function is self-cancelling if you cancel the transaction */
1360 bus_service_remove_owner (BusService *service,
1361 DBusConnection *connection,
1362 BusTransaction *transaction,
1365 BusOwner *primary_owner;
1367 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1369 /* We send out notifications before we do any work we
1370 * might have to undo if the notification-sending failed
1373 /* Send service lost message */
1374 primary_owner = bus_service_get_primary_owner (service);
1375 if (primary_owner != NULL && primary_owner->conn == connection)
1377 if (!bus_driver_send_service_lost (connection, service->name,
1378 transaction, error))
1383 /* if we are not the primary owner then just remove us from the queue */
1385 BusOwner *temp_owner;
1387 link = _bus_service_find_owner_link (service, connection);
1388 _dbus_list_unlink (&service->owners, link);
1389 temp_owner = (BusOwner *)link->data;
1390 bus_owner_unref (temp_owner);
1391 _dbus_list_free_link (link);
1396 if (service->owners == NULL)
1398 _dbus_assert_not_reached ("Tried to remove owner of a service that has no owners");
1400 else if (_dbus_list_length_is_one (&service->owners))
1402 if (!bus_driver_send_service_owner_changed (service->name,
1403 bus_connection_get_name (connection),
1405 transaction, error))
1411 BusOwner *new_owner;
1412 DBusConnection *new_owner_conn;
1413 link = _dbus_list_get_first_link (&service->owners);
1414 _dbus_assert (link != NULL);
1415 link = _dbus_list_get_next_link (&service->owners, link);
1416 _dbus_assert (link != NULL);
1418 new_owner = (BusOwner *)link->data;
1419 new_owner_conn = new_owner->conn;
1421 if (!bus_driver_send_service_owner_changed (service->name,
1422 bus_connection_get_name (connection),
1423 bus_connection_get_name (new_owner_conn),
1424 transaction, error))
1427 /* This will be our new owner */
1428 if (!bus_driver_send_service_acquired (new_owner_conn,
1435 if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
1437 BUS_SET_OOM (error);
1441 bus_service_unlink_owner (service, primary_owner);
1443 if (service->owners == NULL)
1444 bus_service_unlink (service);
1450 bus_service_ref (BusService *service)
1452 _dbus_assert (service->refcount > 0);
1454 service->refcount += 1;
1460 bus_service_unref (BusService *service)
1462 _dbus_assert (service->refcount > 0);
1464 service->refcount -= 1;
1466 if (service->refcount == 0)
1468 _dbus_assert (service->owners == NULL);
1470 dbus_free (service->name);
1471 _dbus_mem_pool_dealloc (service->registry->service_pool, service);
1476 bus_service_get_primary_owners_connection (BusService *service)
1480 owner = bus_service_get_primary_owner (service);
1489 bus_service_get_primary_owner (BusService *service)
1491 return _dbus_list_get_first (&service->owners);
1495 bus_service_get_name (BusService *service)
1497 return service->name;
1501 bus_service_get_allow_replacement (BusService *service)
1506 _dbus_assert (service->owners != NULL);
1508 link = _dbus_list_get_first_link (&service->owners);
1509 owner = (BusOwner *) link->data;
1511 return owner->allow_replacement;
1515 bus_service_has_owner (BusService *service,
1516 DBusConnection *connection)
1520 link = _bus_service_find_owner_link (service, connection);
1529 bus_service_list_queued_owners (BusService *service,
1530 DBusList **return_list,
1535 _dbus_assert (*return_list == NULL);
1537 link = _dbus_list_get_first_link (&service->owners);
1538 _dbus_assert (link != NULL);
1540 while (link != NULL)
1545 owner = (BusOwner *) link->data;
1546 uname = bus_connection_get_name (owner->conn);
1548 if (!_dbus_list_append (return_list, (char *)uname))
1551 link = _dbus_list_get_next_link (&service->owners, link);
1557 _dbus_list_clear (return_list);
1558 BUS_SET_OOM (error);