1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
4 * This file is part of message-port.
6 * Copyright (C) 2013 Intel Corporation.
8 * Contact: Amarnath Valluri <amarnath.valluri@linux.intel.com>
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
29 #include <glib/gstdio.h>
32 #include "common/log.h"
33 #include "dbus-server.h"
34 #include "dbus-manager.h"
38 G_DEFINE_TYPE (MsgPortDbusServer, msgport_dbus_server, G_TYPE_OBJECT)
41 #define MSGPORT_DBUS_SERVER_GET_PRIV(obj) \
42 G_TYPE_INSTANCE_GET_PRIVATE ((obj), MSGPORT_TYPE_DBUS_SERVER, MsgPortDbusServerPrivate)
52 static GParamSpec *properties[N_PROPERTIES];
54 struct _MsgPortDbusServerPrivate
56 GDBusServer *bus_server;
58 GHashTable *dbus_managers; /* {GDBusConnection,MsgPortDbusManager} */
61 static void _on_connection_closed (GDBusConnection *connection,
62 gboolean remote_peer_vanished,
67 _set_property (GObject *object,
69 const GValue *value, GParamSpec *pspec)
71 MsgPortDbusServer *self = MSGPORT_DBUS_SERVER (object);
73 switch (property_id) {
75 self->priv->address = g_value_dup_string (value);
79 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
84 _get_property (GObject *object,
89 MsgPortDbusServer *self = MSGPORT_DBUS_SERVER (object);
91 switch (property_id) {
93 g_value_set_string (value, g_dbus_server_get_client_address (
94 self->priv->bus_server));
98 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
103 _clear_watchers(gpointer connection, gpointer auth_service, gpointer userdata)
105 g_signal_handlers_disconnect_by_func (connection, _on_connection_closed, userdata);
109 _dispose (GObject *object)
111 MsgPortDbusServer *self = MSGPORT_DBUS_SERVER (object);
113 if (self->priv->bus_server) {
114 if (g_dbus_server_is_active (self->priv->bus_server))
115 g_dbus_server_stop (self->priv->bus_server);
116 g_clear_object (&self->priv->bus_server);
119 if (self->priv->dbus_managers) {
120 g_hash_table_foreach (self->priv->dbus_managers, _clear_watchers, self);
121 g_hash_table_unref (self->priv->dbus_managers);
122 self->priv->dbus_managers = NULL;
125 G_OBJECT_CLASS (msgport_dbus_server_parent_class)->dispose (object);
129 _finalize (GObject *object)
131 MsgPortDbusServer *self = MSGPORT_DBUS_SERVER (object);
132 if (self->priv->address) {
133 g_unlink (self->priv->address);
134 g_free (self->priv->address);
135 self->priv->address = NULL;
138 G_OBJECT_CLASS (msgport_dbus_server_parent_class)->finalize (object);
142 msgport_dbus_server_class_init (MsgPortDbusServerClass *klass)
144 GObjectClass* object_class = G_OBJECT_CLASS (klass);
146 g_type_class_add_private (object_class, sizeof (MsgPortDbusServerPrivate));
148 object_class->get_property = _get_property;
149 object_class->set_property = _set_property;
150 object_class->dispose = _dispose;
151 object_class->finalize = _finalize;
153 properties[PROP_ADDRESS] = g_param_spec_string ("address",
155 "Server socket address",
158 G_PARAM_CONSTRUCT_ONLY |
159 G_PARAM_STATIC_STRINGS);
161 g_object_class_install_properties (object_class, N_PROPERTIES, properties);
165 msgport_dbus_server_init (MsgPortDbusServer *self)
167 self->priv = MSGPORT_DBUS_SERVER_GET_PRIV(self);
168 self->priv->bus_server = NULL;
169 self->priv->address = NULL;
171 self->priv->dbus_managers = g_hash_table_new_full (
172 g_direct_hash, g_direct_equal, NULL, g_object_unref);
176 msgport_dbus_server_get_address (MsgPortDbusServer *server)
178 g_return_val_if_fail (server || MSGPORT_IS_DBUS_SERVER (server), NULL);
180 return g_dbus_server_get_client_address (server->priv->bus_server);
184 _on_connection_closed (GDBusConnection *connection,
185 gboolean remote_peer_vanished,
189 MsgPortDbusServer *server = MSGPORT_DBUS_SERVER (user_data);
191 g_signal_handlers_disconnect_by_func (connection, _on_connection_closed, user_data);
192 DBG("dbus connection(%p) closed (peer vanished : %d) : %s",
193 connection, remote_peer_vanished, error ? error->message : "unknwon reason");
195 g_hash_table_remove (server->priv->dbus_managers, connection);
199 msgport_dbus_server_start_dbus_manager_for_connection (
200 MsgPortDbusServer *server,
201 GDBusConnection *connection)
203 MsgPortDbusManager *dbus_manager = NULL;
204 GError *error = NULL;
206 DBG("Starting dbus manager on connection %p", connection);
208 dbus_manager = msgport_dbus_manager_new (
209 connection, server, &error);
211 WARN ("Could not create dbus manager on conneciton %p: %s", connection, error->message);
212 g_error_free (error);
216 g_hash_table_insert (server->priv->dbus_managers, connection, dbus_manager);
218 g_signal_connect (connection, "closed", G_CALLBACK(_on_connection_closed), server);
222 _on_client_request (GDBusServer *dbus_server, GDBusConnection *connection, gpointer userdata)
224 MsgPortDbusServer *server = MSGPORT_DBUS_SERVER(userdata);
226 g_return_val_if_fail (server && MSGPORT_IS_DBUS_SERVER (server), FALSE);
228 msgport_dbus_server_start_dbus_manager_for_connection (server, connection);
234 _start_bus_server (MsgPortDbusServer *server)
238 gchar *address = NULL;
239 const gchar *file_path = NULL;
241 if (!server) return FALSE;
243 if (g_getenv("MESSAGEPORT_BUS_ADDRESS")) {
244 address = g_strdup (g_getenv ("MESSAGEPORT_BUS_ADDRESS"));
247 # ifdef MESSAGEPORT_BUS_ADDRESS
248 address = g_strdup_printf (MESSAGEPORT_BUS_ADDRESS);
252 address = g_strdup_printf ("unix:path=%s/.message-port", g_get_user_runtime_dir());
254 if (g_str_has_prefix(address, "unix:path=")) {
255 file_path = g_strstr_len (address, -1, "unix:path=") + 10;
257 if (g_file_test(file_path, G_FILE_TEST_EXISTS)) {
258 g_unlink (file_path);
261 gchar *base_path = g_path_get_dirname (file_path);
262 if (g_mkdir_with_parents (base_path, S_IRUSR | S_IWUSR | S_IXUSR) == -1) {
263 WARN ("Could not create '%s', error: %s", base_path, strerror(errno));
269 guid = g_dbus_generate_guid ();
271 server->priv->bus_server = g_dbus_server_new_sync (address,
272 G_DBUS_SERVER_FLAGS_NONE, guid, NULL, NULL, &err);
276 if (!server->priv->bus_server) {
277 ERR ("failed to start server at address '%s':%s", server->priv->address,
284 DBG ("Dbus Server started at '%s'", address);
286 server->priv->address = g_strdup (file_path);
288 g_signal_connect (server->priv->bus_server, "new-connection", G_CALLBACK(_on_client_request), server);
290 g_dbus_server_start (server->priv->bus_server);
293 g_chmod (file_path, S_IRUSR | S_IWUSR);
301 msgport_dbus_server_new () {
302 MsgPortDbusServer *server = NULL;
304 server = MSGPORT_DBUS_SERVER (g_object_new (MSGPORT_TYPE_DBUS_SERVER, NULL));
306 _start_bus_server (server);
312 _find_dbus_manager_by_app_id (
313 GDBusConnection *key,
314 MsgPortDbusManager *value,
315 const gchar *app_id_to_find)
317 return !g_strcmp0 (msgport_dbus_manager_get_app_id (value), app_id_to_find);
321 msgport_dbus_server_get_dbus_manager_by_app_id (MsgPortDbusServer *server, const gchar *app_id)
323 g_return_val_if_fail (server && MSGPORT_IS_DBUS_SERVER (server), NULL);
325 return (MsgPortDbusManager *)g_hash_table_find (server->priv->dbus_managers,
326 (GHRFunc)_find_dbus_manager_by_app_id, (gpointer)app_id);