bus.c revision ce173b29fc1e9432cb5956952afdbe775da12415
1/* -*- mode: C; c-file-style: "gnu" -*- */ 2/* bus.c message bus context object 3 * 4 * Copyright (C) 2003 Red Hat, Inc. 5 * 6 * Licensed under the Academic Free License version 1.2 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * 22 */ 23 24#include "bus.h" 25#include "loop.h" 26#include "activation.h" 27#include "connection.h" 28#include "services.h" 29#include "utils.h" 30#include <dbus/dbus-internals.h> 31 32struct BusContext 33{ 34 int refcount; 35 char *address; 36 DBusServer *server; 37 BusConnections *connections; 38 BusActivation *activation; 39 BusRegistry *registry; 40}; 41 42static void 43server_watch_callback (DBusWatch *watch, 44 unsigned int condition, 45 void *data) 46{ 47 BusContext *context = data; 48 49 dbus_server_handle_watch (context->server, watch, condition); 50} 51 52static dbus_bool_t 53add_server_watch (DBusWatch *watch, 54 BusContext *context) 55{ 56 return bus_loop_add_watch (watch, server_watch_callback, context, 57 NULL); 58} 59 60static void 61remove_server_watch (DBusWatch *watch, 62 BusContext *context) 63{ 64 bus_loop_remove_watch (watch, server_watch_callback, context); 65} 66 67 68static void 69server_timeout_callback (DBusTimeout *timeout, 70 void *data) 71{ 72 dbus_timeout_handle (timeout); 73} 74 75static dbus_bool_t 76add_server_timeout (DBusTimeout *timeout, 77 BusContext *context) 78{ 79 return bus_loop_add_timeout (timeout, server_timeout_callback, context, NULL); 80} 81 82static void 83remove_server_timeout (DBusTimeout *timeout, 84 BusContext *context) 85{ 86 bus_loop_remove_timeout (timeout, server_timeout_callback, context); 87} 88 89static void 90new_connection_callback (DBusServer *server, 91 DBusConnection *new_connection, 92 void *data) 93{ 94 BusContext *context = data; 95 96 if (!bus_connections_setup_connection (context->connections, new_connection)) 97 { 98 _dbus_verbose ("No memory to setup new connection\n"); 99 100 /* if we don't do this, it will get unref'd without 101 * being disconnected... kind of strange really 102 * that we have to do this, people won't get it right 103 * in general. 104 */ 105 dbus_connection_disconnect (new_connection); 106 } 107 108 /* on OOM, we won't have ref'd the connection so it will die. */ 109} 110 111BusContext* 112bus_context_new (const char *address, 113 const char **service_dirs, 114 DBusError *error) 115{ 116 BusContext *context; 117 DBusResultCode result; 118 119 context = dbus_new0 (BusContext, 1); 120 if (context == NULL) 121 { 122 BUS_SET_OOM (error); 123 return NULL; 124 } 125 126 context->refcount = 1; 127 128 context->address = _dbus_strdup (address); 129 if (context->address == NULL) 130 { 131 BUS_SET_OOM (error); 132 goto failed; 133 } 134 135 context->server = dbus_server_listen (address, &result); 136 if (context->server == NULL) 137 { 138 dbus_set_error (error, DBUS_ERROR_FAILED, 139 "Failed to start server on %s: %s\n", 140 address, dbus_result_to_string (result)); 141 goto failed; 142 } 143 144 context->activation = bus_activation_new (address, service_dirs, 145 error); 146 if (context->activation == NULL) 147 { 148 _DBUS_ASSERT_ERROR_IS_SET (error); 149 goto failed; 150 } 151 152 context->connections = bus_connections_new (context); 153 if (context->connections == NULL) 154 { 155 BUS_SET_OOM (error); 156 goto failed; 157 } 158 159 context->registry = bus_registry_new (); 160 if (context->registry == NULL) 161 { 162 BUS_SET_OOM (error); 163 goto failed; 164 } 165 166 dbus_server_set_new_connection_function (context->server, 167 new_connection_callback, 168 context, NULL); 169 170 if (!dbus_server_set_watch_functions (context->server, 171 (DBusAddWatchFunction) add_server_watch, 172 (DBusRemoveWatchFunction) remove_server_watch, 173 NULL, 174 context, 175 NULL)) 176 { 177 BUS_SET_OOM (error); 178 goto failed; 179 } 180 181 if (!dbus_server_set_timeout_functions (context->server, 182 (DBusAddTimeoutFunction) add_server_timeout, 183 (DBusRemoveTimeoutFunction) remove_server_timeout, 184 NULL, 185 context, NULL)) 186 { 187 BUS_SET_OOM (error); 188 goto failed; 189 } 190 191 return context; 192 193 failed: 194 bus_context_unref (context); 195 return NULL; 196} 197 198void 199bus_context_shutdown (BusContext *context) 200{ 201 if (context->server == NULL || 202 !dbus_server_get_is_connected (context->server)) 203 return; 204 205 if (!dbus_server_set_watch_functions (context->server, 206 NULL, NULL, NULL, 207 context, 208 NULL)) 209 _dbus_assert_not_reached ("setting watch functions to NULL failed"); 210 211 if (!dbus_server_set_timeout_functions (context->server, 212 NULL, NULL, NULL, 213 context, 214 NULL)) 215 _dbus_assert_not_reached ("setting timeout functions to NULL failed"); 216 217 dbus_server_disconnect (context->server); 218} 219 220void 221bus_context_ref (BusContext *context) 222{ 223 _dbus_assert (context->refcount > 0); 224 context->refcount += 1; 225} 226 227void 228bus_context_unref (BusContext *context) 229{ 230 _dbus_assert (context->refcount > 0); 231 context->refcount -= 1; 232 233 if (context->refcount == 0) 234 { 235 _dbus_verbose ("Finalizing bus context %p\n", context); 236 237 bus_context_shutdown (context); 238 239 if (context->connections) 240 { 241 bus_connections_unref (context->connections); 242 context->connections = NULL; 243 } 244 245 if (context->registry) 246 { 247 bus_registry_unref (context->registry); 248 context->registry = NULL; 249 } 250 251 if (context->activation) 252 { 253 bus_activation_unref (context->activation); 254 context->activation = NULL; 255 } 256 257 if (context->server) 258 { 259 dbus_server_unref (context->server); 260 context->server = NULL; 261 } 262 263 dbus_free (context->address); 264 dbus_free (context); 265 } 266} 267 268BusRegistry* 269bus_context_get_registry (BusContext *context) 270{ 271 return context->registry; 272} 273 274BusConnections* 275bus_context_get_connections (BusContext *context) 276{ 277 return context->connections; 278} 279 280BusActivation* 281bus_context_get_activation (BusContext *context) 282{ 283 return context->activation; 284} 285