diff options
Diffstat (limited to 'bus/bus.c')
-rw-r--r-- | bus/bus.c | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/bus/bus.c b/bus/bus.c new file mode 100644 index 00000000..7ac0beee --- /dev/null +++ b/bus/bus.c @@ -0,0 +1,202 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* bus.c message bus context object + * + * Copyright (C) 2003 Red Hat, Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "bus.h" +#include "loop.h" +#include "activation.h" +#include "connection.h" +#include "services.h" +#include "utils.h" +#include <dbus/dbus-internals.h> + +struct BusContext +{ + int refcount; + char *address; + DBusServer *server; + BusConnections *connections; + BusActivation *activation; + BusRegistry *registry; +}; + +static void +server_watch_callback (DBusWatch *watch, + unsigned int condition, + void *data) +{ + BusContext *context = data; + + dbus_server_handle_watch (context->server, watch, condition); +} + +static void +add_server_watch (DBusWatch *watch, + BusContext *context) +{ + bus_loop_add_watch (watch, server_watch_callback, context, + NULL); +} + +static void +remove_server_watch (DBusWatch *watch, + BusContext *context) +{ + bus_loop_remove_watch (watch, server_watch_callback, context); +} + +static void +new_connection_callback (DBusServer *server, + DBusConnection *new_connection, + void *data) +{ + BusContext *context = data; + + if (!bus_connections_setup_connection (context->connections, new_connection)) + _dbus_verbose ("No memory to setup new connection\n"); + + /* on OOM, we won't have ref'd the connection so it will die */ +} + +BusContext* +bus_context_new (const char *address, + const char **service_dirs, + DBusError *error) +{ + BusContext *context; + DBusResultCode result; + + context = dbus_new0 (BusContext, 1); + if (context == NULL) + { + BUS_SET_OOM (error); + return NULL; + } + + context->refcount = 1; + + context->address = _dbus_strdup (address); + if (context->address == NULL) + { + BUS_SET_OOM (error); + goto failed; + } + + context->server = dbus_server_listen (address, &result); + if (context->server == NULL) + { + dbus_set_error (error, DBUS_ERROR_FAILED, + "Failed to start server on %s: %s\n", + address, dbus_result_to_string (result)); + goto failed; + } + + context->activation = bus_activation_new (address, service_dirs, + error); + if (context->activation == NULL) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + goto failed; + } + + context->connections = bus_connections_new (context); + if (context->connections == NULL) + { + BUS_SET_OOM (error); + goto failed; + } + + context->registry = bus_registry_new (); + if (context->registry == NULL) + { + BUS_SET_OOM (error); + goto failed; + } + + dbus_server_set_new_connection_function (context->server, + new_connection_callback, + context, NULL); + + dbus_server_set_watch_functions (context->server, + (DBusAddWatchFunction) add_server_watch, + (DBusRemoveWatchFunction) remove_server_watch, + context, + NULL); + + return context; + + failed: + bus_context_unref (context); + return NULL; +} + +void +bus_context_shutdown (BusContext *context) +{ + dbus_server_disconnect (context->server); +} + +void +bus_context_ref (BusContext *context) +{ + _dbus_assert (context->refcount > 0); + context->refcount += 1; +} + +void +bus_context_unref (BusContext *context) +{ + _dbus_assert (context->refcount > 0); + context->refcount -= 1; + + if (context->refcount == 0) + { + if (context->registry) + bus_registry_unref (context->registry); + if (context->connections) + bus_connections_unref (context->connections); + if (context->activation) + bus_activation_unref (context->activation); + if (context->server) + dbus_server_unref (context->server); + dbus_free (context->address); + dbus_free (context); + } +} + +BusRegistry* +bus_context_get_registry (BusContext *context) +{ + return context->registry; +} + +BusConnections* +bus_context_get_connections (BusContext *context) +{ + return context->connections; +} + +BusActivation* +bus_context_get_activation (BusContext *context) +{ + return context->activation; +} |