summaryrefslogtreecommitdiff
path: root/dispatcher
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2007-10-09 01:42:26 +0200
committerCarlos Garnacho <carlosg@gnome.org>2007-10-09 01:42:26 +0200
commitb4dff3c2a1fa42acb352abababfcafd9774078b7 (patch)
treefe1b0b62225db3389ac4e98010910e965d63c916 /dispatcher
parenta3b5d134c85be37f861f408f143f9cd7533bbed1 (diff)
GObjectify dispatcher
StbDispatcher lives in dispatcher.[ch] and the main routine lives in main.c
Diffstat (limited to 'dispatcher')
-rw-r--r--dispatcher/Makefile.am3
-rw-r--r--dispatcher/dispatcher.c345
-rw-r--r--dispatcher/dispatcher.h57
-rw-r--r--dispatcher/main.c110
4 files changed, 368 insertions, 147 deletions
diff --git a/dispatcher/Makefile.am b/dispatcher/Makefile.am
index 871e6fa..e14a952 100644
--- a/dispatcher/Makefile.am
+++ b/dispatcher/Makefile.am
@@ -6,4 +6,5 @@ bin_PROGRAMS = system-tools-backends
system_tools_backends_LDADD = $(DISPATCHER_LIBS)
system_tools_backends_SOURCES = \
- dispatcher.c
+ dispatcher.c dispatcher.h \
+ main.c
diff --git a/dispatcher/dispatcher.c b/dispatcher/dispatcher.c
index a888d4a..c4d7b11 100644
--- a/dispatcher/dispatcher.c
+++ b/dispatcher/dispatcher.c
@@ -18,43 +18,135 @@
* Authors: Carlos Garnacho Parro <carlosg@gnome.org>
*/
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+
#include <glib.h>
#include <glib-object.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib-lowlevel.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <signal.h>
-#include "config.h"
+#include "dispatcher.h"
#define DBUS_ADDRESS_ENVVAR "DBUS_SESSION_BUS_ADDRESS"
#define DBUS_INTERFACE_STB "org.freedesktop.SystemToolsBackends"
#define DBUS_INTERFACE_STB_PLATFORM "org.freedesktop.SystemToolsBackends.Platform"
-/* FIXME: should be inside an object */
-static GPid bus_pid = 0;
-static guint watch_id = 0;
-static gchar *platform = NULL;
+#define STB_DISPATCHER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), STB_TYPE_DISPATCHER, StbDispatcherPrivate))
-typedef struct {
+typedef struct StbDispatcherPrivate StbDispatcherPrivate;
+typedef struct StbDispatcherAsyncData StbDispatcherAsyncData;
+
+struct StbDispatcherPrivate
+{
DBusConnection *connection;
+ DBusConnection *session_connection;
+
+ GPid bus_pid;
+ guint watch_id;
+ gchar *platform;
+};
+
+struct StbDispatcherAsyncData
+{
+ StbDispatcher *dispatcher;
gchar *destination;
gint serial;
-} AsyncData;
+};
+
+static void stb_dispatcher_class_init (StbDispatcherClass *class);
+static void stb_dispatcher_init (StbDispatcher *object);
+static void stb_dispatcher_finalize (GObject *object);
+
+static GObject* stb_dispatcher_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params);
+
+
+G_DEFINE_TYPE (StbDispatcher, stb_dispatcher, G_TYPE_OBJECT);
static void
-async_data_free (AsyncData *data)
+stb_dispatcher_class_init (StbDispatcherClass *class)
{
- dbus_connection_unref (data->connection);
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->constructor = stb_dispatcher_constructor;
+ object_class->finalize = stb_dispatcher_finalize;
+
+ g_type_class_add_private (object_class,
+ sizeof (StbDispatcherPrivate));
+}
+
+static void
+on_bus_term (GPid pid,
+ gint status,
+ gpointer data)
+{
+ StbDispatcher *dispatcher;
+ StbDispatcherPrivate *priv;
+
+ dispatcher = STB_DISPATCHER (data);
+ priv = dispatcher->_priv;
+
+ g_spawn_close_pid (priv->bus_pid);
+ priv->bus_pid = 0;
+
+ /* if the bus dies, we screwed up */
+ g_critical ("Can't live without bus.");
+ g_assert_not_reached ();
+}
+
+static void
+setup_private_bus (StbDispatcher *dispatcher)
+{
+ StbDispatcherPrivate *priv;
+ DBusError error;
+
+ priv = STB_DISPATCHER_GET_PRIVATE (dispatcher);
+ dbus_error_init (&error);
+
+ if (!priv->bus_pid)
+ {
+ /* spawn private bus */
+ static gchar *argv[] = { "dbus-daemon", "--session", "--print-address", "--nofork", NULL };
+ gint output_fd, size;
+ gchar *envvar;
+ gchar str[300] = { 0, };
+
+ if (!g_spawn_async_with_pipes (NULL, argv, NULL,
+ G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
+ NULL, NULL, &priv->bus_pid,
+ NULL, &output_fd, NULL, NULL))
+ return;
+
+ priv->watch_id = g_child_watch_add (priv->bus_pid, on_bus_term, dispatcher);
+ size = read (output_fd, str, sizeof (str));
+ str[size - 1] = '\0';
+
+ envvar = g_strdup_printf (DBUS_ADDRESS_ENVVAR "=%s", str);
+ putenv (envvar);
+
+ /* get a connection with the newly created bus */
+ priv->session_connection = dbus_bus_get (DBUS_BUS_SESSION, &error);
+
+ if (dbus_error_is_set (&error))
+ g_critical (error.message);
+
+ dbus_connection_set_exit_on_disconnect (priv->session_connection, FALSE);
+ dbus_connection_setup_with_g_main (priv->session_connection, NULL);
+ }
+}
+
+static void
+async_data_free (StbDispatcherAsyncData *data)
+{
+ g_object_unref (data->dispatcher);
g_free (data->destination);
g_free (data);
}
-static void
+static gchar *
retrieve_platform (DBusMessage *message)
{
DBusMessageIter iter;
@@ -64,28 +156,32 @@ retrieve_platform (DBusMessage *message)
dbus_message_iter_get_basic (&iter, &str);
if (str && *str)
- platform = g_strdup (str);
+ return g_strdup (str);
+
+ return NULL;
}
static void
dispatch_reply (DBusPendingCall *pending_call,
gpointer data)
{
+ StbDispatcherPrivate *priv;
DBusMessage *reply;
- AsyncData *async_data;
+ StbDispatcherAsyncData *async_data;
reply = dbus_pending_call_steal_reply (pending_call);
- async_data = (AsyncData *) data;
+ async_data = (StbDispatcherAsyncData *) data;
+ priv = async_data->dispatcher->_priv;
/* get the platform if necessary */
if (dbus_message_has_interface (reply, DBUS_INTERFACE_STB_PLATFORM) &&
- dbus_message_has_member (reply, "getPlatform") && !platform)
- retrieve_platform (reply);
+ dbus_message_has_member (reply, "getPlatform") && !priv->platform)
+ priv->platform = retrieve_platform (reply);
/* send the reply back */
dbus_message_set_destination (reply, async_data->destination);
dbus_message_set_reply_serial (reply, async_data->serial);
- dbus_connection_send (async_data->connection, reply, NULL);
+ dbus_connection_send (priv->connection, reply, NULL);
dbus_message_unref (reply);
}
@@ -113,18 +209,20 @@ get_destination (DBusMessage *message)
}
static void
-dispatch_stb_message (DBusConnection *connection,
- DBusConnection *session_connection,
- DBusMessage *message)
+dispatch_stb_message (StbDispatcher *dispatcher,
+ DBusMessage *message)
{
+ StbDispatcherPrivate *priv;
DBusMessage *copy;
DBusPendingCall *pending_call;
- AsyncData *async_data;
+ StbDispatcherAsyncData *async_data;
gchar *destination;
+ priv = STB_DISPATCHER_GET_PRIVATE (dispatcher);
+
if (dbus_message_has_interface (message, DBUS_INTERFACE_STB_PLATFORM))
{
- if (dbus_message_has_member (message, "getPlatform") && platform)
+ if (dbus_message_has_member (message, "getPlatform") && priv->platform)
{
DBusMessage *reply;
DBusMessageIter iter;
@@ -132,33 +230,36 @@ dispatch_stb_message (DBusConnection *connection,
/* create a reply with the stored platform */
reply = dbus_message_new_method_return (message);
dbus_message_iter_init_append (reply, &iter);
- dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &platform);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &priv->platform);
- dbus_connection_send (connection, reply, NULL);
+ dbus_connection_send (priv->connection, reply, NULL);
dbus_message_unref (reply);
return;
}
else if (dbus_message_has_member (message, "setPlatform"))
- retrieve_platform (message);
+ priv->platform = retrieve_platform (message);
}
destination = get_destination (message);
/* there's something wrong with the message */
- if (!destination)
- return;
+ if (G_UNLIKELY (!destination))
+ {
+ g_critical ("Could not get a valid destination, original one was: %s", dbus_message_get_path (message));
+ return;
+ }
copy = dbus_message_copy (message);
/* forward the message to the corresponding service */
dbus_message_set_destination (copy, destination);
- dbus_connection_send_with_reply (session_connection, copy, &pending_call, -1);
+ dbus_connection_send_with_reply (priv->session_connection, copy, &pending_call, -1);
if (pending_call)
{
- async_data = g_new0 (AsyncData, 1);
- async_data->connection = dbus_connection_ref (connection);
+ async_data = g_new0 (StbDispatcherAsyncData, 1);
+ async_data->dispatcher = g_object_ref (dispatcher);
async_data->destination = g_strdup (dbus_message_get_sender (message));
async_data->serial = dbus_message_get_serial (message);
@@ -175,7 +276,7 @@ dispatcher_filter_func (DBusConnection *connection,
DBusMessage *message,
void *data)
{
- DBusConnection *session_connection = (DBusConnection *) data;
+ StbDispatcher *dispatcher = STB_DISPATCHER (data);
if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected"))
{
@@ -188,146 +289,98 @@ dispatcher_filter_func (DBusConnection *connection,
else if (dbus_message_has_interface (message, DBUS_INTERFACE_INTROSPECTABLE) ||
dbus_message_has_interface (message, DBUS_INTERFACE_STB) ||
dbus_message_has_interface (message, DBUS_INTERFACE_STB_PLATFORM))
- dispatch_stb_message (connection, session_connection, message);
+ dispatch_stb_message (dispatcher, message);
return DBUS_HANDLER_RESULT_HANDLED;
}
static void
-daemonize (void)
+setup_connection (StbDispatcher *dispatcher)
{
- int dev_null_fd, pidfile_fd;
- gchar *str;
-
- if (!getenv ("STB_NO_DAEMON"))
- {
- dev_null_fd = open ("/dev/null", O_RDWR);
-
- dup2 (dev_null_fd, 0);
- dup2 (dev_null_fd, 1);
- dup2 (dev_null_fd, 2);
+ StbDispatcherPrivate *priv;
+ DBusError error;
- if (fork () != 0)
- exit (0);
+ priv = STB_DISPATCHER_GET_PRIVATE (dispatcher);
+ dbus_error_init (&error);
- setsid ();
+ priv->connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
- if ((pidfile_fd = open (LOCALSTATEDIR "/run/system-tools-backends.pid", O_CREAT | O_WRONLY)) != -1)
- {
- str = g_strdup_printf ("%d", getpid ());
- write (pidfile_fd, str, strlen (str));
- g_free (str);
+ if (dbus_error_is_set (&error))
+ {
+ g_critical (error.message);
+ dbus_error_free (&error);
+ }
- close (pidfile_fd);
- }
+ dbus_connection_set_exit_on_disconnect (priv->connection, FALSE);
+ dbus_connection_add_filter (priv->connection, dispatcher_filter_func, dispatcher, NULL);
+ dbus_bus_request_name (priv->connection, DBUS_INTERFACE_STB, 0, &error);
- close (dev_null_fd);
+ if (dbus_error_is_set (&error))
+ {
+ g_critical (error.message);
+ dbus_error_free (&error);
}
+
+ dbus_connection_setup_with_g_main (priv->connection, NULL);
}
static void
-on_bus_term (GPid pid,
- gint status,
- gpointer data)
+stb_dispatcher_init (StbDispatcher *dispatcher)
{
- g_spawn_close_pid (pid);
- bus_pid = 0;
+ StbDispatcherPrivate *priv;
- /* if the bus dies, we screwed up */
- g_critical ("Can't live without bus.");
- g_assert_not_reached ();
-}
+ priv = STB_DISPATCHER_GET_PRIVATE (dispatcher);
+ dispatcher->_priv = priv;
-static DBusConnection*
-get_private_bus (void)
-{
- DBusConnection *connection = NULL;
- DBusError error;
+ setup_private_bus (dispatcher);
+ setup_connection (dispatcher);
- dbus_error_init (&error);
-
- if (!bus_pid)
- {
- /* spawn private bus */
- static gchar *argv[] = { "dbus-daemon", "--session", "--print-address", "--nofork", NULL };
- gint output_fd, size;
- gchar *envvar;
- gchar str[300] = { 0, };
+ /* we're screwed if we don't have these */
+ g_assert (priv->session_connection != NULL);
+ g_assert (priv->connection != NULL);
+}
- if (!g_spawn_async_with_pipes (NULL, argv, NULL,
- G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
- NULL, NULL, &bus_pid,
- NULL, &output_fd, NULL, NULL))
- return NULL;
+static void
+stb_dispatcher_finalize (GObject *object)
+{
+ StbDispatcherPrivate *priv;
- watch_id = g_child_watch_add (bus_pid, on_bus_term, NULL);
- size = read (output_fd, str, sizeof (str));
- str[size - 1] = '\0';
+ priv = STB_DISPATCHER_GET_PRIVATE (object);
- envvar = g_strdup_printf (DBUS_ADDRESS_ENVVAR "=%s", str);
- putenv (envvar);
+ dbus_connection_unref (priv->session_connection);
+ dbus_connection_unref (priv->connection);
- /* get a connection with the newly created bus */
- connection = dbus_bus_get (DBUS_BUS_SESSION, &error);
+ /* terminate the private bus */
+ if (priv->bus_pid)
+ {
+ g_source_remove (priv->watch_id);
+ priv->watch_id = 0;
- if (dbus_error_is_set (&error))
- g_critical (error.message);
+ kill (priv->bus_pid, SIGTERM);
+ priv->bus_pid = 0;
}
- return connection;
+ g_free (priv->platform);
+
+ G_OBJECT_CLASS (stb_dispatcher_parent_class)->finalize (object);
}
-void
-kill_private_bus (gint signal)
+static GObject*
+stb_dispatcher_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
{
- /* terminate the private bus */
- if (bus_pid)
- {
- g_source_remove (watch_id);
- kill (bus_pid, SIGTERM);
- }
+ static GObject *object = NULL;
- exit (0);
+ if (!object)
+ object = G_OBJECT_CLASS (stb_dispatcher_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_params);
+ return object;
}
-int
-main (int argc, char *argv[])
+StbDispatcher*
+stb_dispatcher_get (void)
{
- DBusConnection *connection, *session_connection;
- GMainLoop *main_loop;
- DBusError error;
-
- /* Currently not necessary, we're not using objects */
- /* g_type_init (); */
- dbus_error_init (&error);
-
- daemonize ();
- signal (SIGTERM, kill_private_bus);
-
- session_connection = get_private_bus ();
- connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
-
- if (!session_connection || !connection)
- {
- kill_private_bus (0);
- exit (-1);
- }
-
- dbus_connection_set_exit_on_disconnect (connection, FALSE);
- dbus_connection_set_exit_on_disconnect (session_connection, FALSE);
-
- dbus_connection_add_filter (connection, dispatcher_filter_func, session_connection, NULL);
- dbus_bus_request_name (connection, DBUS_INTERFACE_STB, 0, &error);
-
- if (dbus_error_is_set (&error))
- g_critical (error.message);
-
-
- dbus_connection_setup_with_g_main (connection, NULL);
- dbus_connection_setup_with_g_main (session_connection, NULL);
-
- main_loop = g_main_loop_new (NULL, FALSE);
- g_main_loop_run (main_loop);
-
- return 0;
+ return g_object_new (STB_TYPE_DISPATCHER, NULL);
}
diff --git a/dispatcher/dispatcher.h b/dispatcher/dispatcher.h
new file mode 100644
index 0000000..063e64b
--- /dev/null
+++ b/dispatcher/dispatcher.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */
+/* Copyright (C) 2006 Carlos Garnacho
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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.
+ *
+ * Authors: Carlos Garnacho Parro <carlosg@gnome.org>
+ */
+
+#ifndef __STB_DISPATCHER_H
+#define __STB_DISPATCHER_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define STB_TYPE_DISPATCHER (stb_dispatcher_get_type ())
+#define STB_DISPATCHER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), STB_TYPE_DISPATCHER, StbDispatcher))
+#define STB_DISPATCHER_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), STB_TYPE_DISPATCHER, StbDispatcherClass))
+#define STB_IS_DISPATCHER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), STB_TYPE_DISPATCHER))
+#define STB_IS_DISPATCHER_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((o), STB_TYPE_DISPATCHER))
+#define STB_DISPATCHER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), STB_TYPE_DISPATCHER, StbDispatcherClass))
+
+typedef struct StbDispatcher StbDispatcher;
+typedef struct StbDispatcherClass StbDispatcherClass;
+
+struct StbDispatcher
+{
+ GObject parent;
+
+ /*<private>*/
+ gpointer _priv;
+};
+
+struct StbDispatcherClass
+{
+ GObjectClass parent_class;
+};
+
+GType stb_dispatcher_get_type (void);
+
+StbDispatcher *stb_dispatcher_get (void);
+
+G_END_DECLS
+
+#endif /* __STB_DISPATCHER_H */
diff --git a/dispatcher/main.c b/dispatcher/main.c
new file mode 100644
index 0000000..c2861fe
--- /dev/null
+++ b/dispatcher/main.c
@@ -0,0 +1,110 @@
+/* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */
+/* Copyright (C) 2006 Carlos Garnacho
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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.
+ *
+ * Authors: Carlos Garnacho Parro <carlosg@gnome.org>
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <stdlib.h>
+#include "dispatcher.h"
+#include "config.h"
+
+static StbDispatcher *dispatcher = NULL;
+
+static void
+daemonize (void)
+{
+ int dev_null_fd, pidfile_fd;
+ gchar *str;
+
+ dev_null_fd = open ("/dev/null", O_RDWR);
+
+ dup2 (dev_null_fd, 0);
+ dup2 (dev_null_fd, 1);
+ dup2 (dev_null_fd, 2);
+
+ if (fork () != 0)
+ exit (0);
+
+ setsid ();
+
+ if ((pidfile_fd = open (LOCALSTATEDIR "/run/system-tools-backends.pid", O_CREAT | O_WRONLY)) != -1)
+ {
+ str = g_strdup_printf ("%d", getpid ());
+ write (pidfile_fd, str, strlen (str));
+ g_free (str);
+
+ close (pidfile_fd);
+ }
+
+ close (dev_null_fd);
+}
+
+void
+signal_received (gint signal)
+{
+ switch (signal)
+ {
+ case SIGTERM:
+ case SIGABRT:
+ g_object_unref (dispatcher);
+ exit (0);
+ break;
+ default:
+ break;
+ }
+}
+
+int
+main (int argc, char *argv[])
+{
+ GMainLoop *main_loop;
+ gboolean debug = FALSE;
+ gboolean no_daemon = FALSE;
+ GOptionContext *context;
+ GOptionEntry entries[] =
+ {
+ { "debug", 'd', 0, G_OPTION_ARG_NONE, &debug, "Debug mode", NULL },
+ { "no-daemon", 'n', 0, G_OPTION_ARG_NONE, &no_daemon, "No daemon mode", NULL },
+ { NULL }
+ };
+
+ g_type_init ();
+
+ /* parse options */
+ context = g_option_context_new (NULL);
+ g_option_context_add_main_entries (context, entries, NULL);
+ g_option_context_parse (context, &argc, &argv, NULL);
+ g_option_context_free (context);
+
+ /* keep the envvar for backwards compat */
+ if (!no_daemon && !getenv ("STB_NO_DAEMON"))
+ daemonize ();
+
+ signal (SIGTERM, signal_received);
+ dispatcher = stb_dispatcher_get ();
+
+ main_loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (main_loop);
+
+ return 0;
+}