services.c revision 97ee8d189948c9f2c86464ca33f82e6daeaedc72
1/* -*- mode: C; c-file-style: "gnu" -*- */ 2/* services.c Service management 3 * 4 * Copyright (C) 2003 Red Hat, Inc. 5 * Copyright (C) 2003 CodeFactory AB 6 * 7 * Licensed under the Academic Free License version 1.2 8 * 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. 13 * 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. 18 * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 * 23 */ 24#include "driver.h" 25#include "services.h" 26#include "connection.h" 27#include <dbus/dbus-hash.h> 28#include <dbus/dbus-list.h> 29#include <dbus/dbus-mempool.h> 30 31struct BusService 32{ 33 char *name; 34 DBusList *owners; 35 36 unsigned int prohibit_replacement:1; 37}; 38 39static DBusHashTable *service_hash = NULL; 40static DBusMemPool *service_pool = NULL; 41 42BusService* 43bus_service_lookup (const DBusString *service_name, 44 dbus_bool_t create_if_not_found) 45{ 46 const char *c_name; 47 BusService *service; 48 49 if (service_hash == NULL) 50 { 51 service_hash = _dbus_hash_table_new (DBUS_HASH_STRING, 52 NULL, NULL); 53 service_pool = _dbus_mem_pool_new (sizeof (BusService), 54 TRUE); 55 56 if (service_hash == NULL || service_pool == NULL) 57 { 58 if (service_hash) 59 { 60 _dbus_hash_table_unref (service_hash); 61 service_hash = NULL; 62 } 63 if (service_pool) 64 { 65 _dbus_mem_pool_free (service_pool); 66 service_pool = NULL; 67 } 68 return NULL; 69 } 70 } 71 72 _dbus_string_get_const_data (service_name, &c_name); 73 74 service = _dbus_hash_table_lookup_string (service_hash, 75 c_name); 76 if (service != NULL) 77 return service; 78 79 if (!create_if_not_found) 80 return NULL; 81 82 service = _dbus_mem_pool_alloc (service_pool); 83 if (service == NULL) 84 return NULL; 85 86 service->name = _dbus_strdup (c_name); 87 if (service->name == NULL) 88 { 89 _dbus_mem_pool_dealloc (service_pool, service); 90 return NULL; 91 } 92 93 if (!_dbus_hash_table_insert_string (service_hash, 94 service->name, 95 service)) 96 { 97 dbus_free (service->name); 98 _dbus_mem_pool_dealloc (service_pool, service); 99 return NULL; 100 } 101 102 bus_driver_send_service_created (service->name); 103 104 return service; 105} 106 107dbus_bool_t 108bus_service_add_owner (BusService *service, 109 DBusConnection *owner) 110{ 111 if (!_dbus_list_append (&service->owners, 112 owner)) 113 return FALSE; 114 115 if (!bus_connection_add_owned_service (owner, service)) 116 { 117 _dbus_list_remove_last (&service->owners, owner); 118 return FALSE; 119 } 120 121 /* Send service acquired message */ 122 if (bus_service_get_primary_owner (service) == owner) 123 bus_driver_send_service_acquired (owner, service->name); 124 125 return TRUE; 126} 127 128void 129bus_service_remove_owner (BusService *service, 130 DBusConnection *owner) 131{ 132 /* Send service lost message */ 133 if (bus_service_get_primary_owner (service) == owner) 134 bus_driver_send_service_lost (owner, service->name); 135 136 _dbus_list_remove_last (&service->owners, owner); 137 bus_connection_remove_owned_service (owner, service); 138 139 if (service->owners == NULL) 140 { 141 /* Delete service */ 142 bus_driver_send_service_deleted (service->name); 143 144 _dbus_hash_table_remove_string (service_hash, service->name); 145 146 dbus_free (service->name); 147 _dbus_mem_pool_dealloc (service_pool, service); 148 } 149 else 150 { 151 /* Send service acquired to the new owner */ 152 bus_driver_send_service_acquired (bus_service_get_primary_owner (service), 153 service->name); 154 } 155} 156 157DBusConnection* 158bus_service_get_primary_owner (BusService *service) 159{ 160 return _dbus_list_get_first (&service->owners); 161} 162 163const char* 164bus_service_get_name (BusService *service) 165{ 166 return service->name; 167} 168 169void 170bus_service_foreach (BusServiceForeachFunction function, 171 void *data) 172{ 173 DBusHashIter iter; 174 175 if (service_hash == NULL) 176 return; 177 178 _dbus_hash_iter_init (service_hash, &iter); 179 while (_dbus_hash_iter_next (&iter)) 180 { 181 BusService *service = _dbus_hash_iter_get_value (&iter); 182 183 (* function) (service, data); 184 } 185} 186 187char ** 188bus_services_list (int *array_len) 189{ 190 int i, j, len; 191 char **retval; 192 DBusHashIter iter; 193 194 len = _dbus_hash_table_get_n_entries (service_hash); 195 retval = dbus_new (char *, len); 196 197 if (retval == NULL) 198 return NULL; 199 200 _dbus_hash_iter_init (service_hash, &iter); 201 i = 0; 202 while (_dbus_hash_iter_next (&iter)) 203 { 204 BusService *service = _dbus_hash_iter_get_value (&iter); 205 206 retval[i] = _dbus_strdup (service->name); 207 if (retval[i] == NULL) 208 goto error; 209 210 i++; 211 } 212 213 if (array_len) 214 *array_len = len; 215 216 return retval; 217 218 error: 219 for (j = 0; j < i; j++) 220 dbus_free (retval[i]); 221 dbus_free (retval); 222 223 return NULL; 224} 225 226void 227bus_service_set_prohibit_replacement (BusService *service, 228 dbus_bool_t prohibit_replacement) 229{ 230 _dbus_assert (service->owners == NULL); 231 232 service->prohibit_replacement = prohibit_replacement != FALSE; 233} 234 235dbus_bool_t 236bus_service_get_prohibit_replacement (BusService *service) 237{ 238 return service->prohibit_replacement; 239} 240 241dbus_bool_t 242bus_service_has_owner (BusService *service, 243 DBusConnection *owner) 244{ 245 DBusList *link; 246 247 link = _dbus_list_get_first_link (&service->owners); 248 249 while (link != NULL) 250 { 251 if (link->data == owner) 252 return TRUE; 253 254 link = _dbus_list_get_next_link (&service->owners, link); 255 } 256 257 return FALSE; 258} 259