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 gsignond
6 * Copyright (C) 2013 Intel Corporation.
8 * Contact: Imran Zaman <imran.zaman@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
26 #include "gsignond/gsignond-plugin-interface.h"
27 #include "gsignond/gsignond-log.h"
28 #include "gsignond/gsignond-error.h"
29 #include "common/gsignond-plugin-loader.h"
30 #include "common/gsignond-pipe-stream.h"
31 #include "daemon/dbus/gsignond-dbus-remote-plugin-gen.h"
32 #include "daemon/dbus/gsignond-dbus.h"
33 #include "gsignond-plugin-daemon.h"
35 struct _GSignondPluginDaemonPrivate
37 GDBusConnection *connection;
38 GSignondDbusRemotePlugin *dbus_remote_plugin;
39 GSignondPlugin *plugin;
43 G_DEFINE_TYPE (GSignondPluginDaemon, gsignond_plugin_daemon, G_TYPE_OBJECT)
46 #define GSIGNOND_PLUGIN_DAEMON_GET_PRIV(obj) \
47 G_TYPE_INSTANCE_GET_PRIVATE ((obj), GSIGNOND_TYPE_PLUGIN_DAEMON,\
48 GSignondPluginDaemonPrivate)
51 _dispose (GObject *object)
53 GSignondPluginDaemon *self = GSIGNOND_PLUGIN_DAEMON (object);
55 if (self->priv->dbus_remote_plugin) {
56 g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (
57 self->priv->dbus_remote_plugin));
58 g_object_unref (self->priv->dbus_remote_plugin);
59 self->priv->dbus_remote_plugin = NULL;
62 if (self->priv->connection) {
63 g_object_unref (self->priv->connection);
64 self->priv->connection = NULL;
67 if (self->priv->plugin) {
68 g_object_unref (self->priv->plugin);
69 self->priv->plugin = NULL;
72 G_OBJECT_CLASS (gsignond_plugin_daemon_parent_class)->dispose (object);
76 _finalize (GObject *object)
78 GSignondPluginDaemon *self = GSIGNOND_PLUGIN_DAEMON (object);
80 if (self->priv->plugin_type) {
81 g_free (self->priv->plugin_type);
82 self->priv->plugin_type = NULL;
85 G_OBJECT_CLASS (gsignond_plugin_daemon_parent_class)->finalize (object);
89 gsignond_plugin_daemon_class_init (
90 GSignondPluginDaemonClass *klass)
92 GObjectClass* object_class = G_OBJECT_CLASS (klass);
94 g_type_class_add_private (object_class, sizeof (
95 GSignondPluginDaemonPrivate));
97 object_class->dispose = _dispose;
98 object_class->finalize = _finalize;
103 gsignond_plugin_daemon_init (
104 GSignondPluginDaemon *self)
106 self->priv = GSIGNOND_PLUGIN_DAEMON_GET_PRIV(self);
107 self->priv->connection = NULL;
108 self->priv->dbus_remote_plugin = NULL;
109 self->priv->plugin_type = NULL;
110 self->priv->plugin = NULL;
114 _on_connection_closed (
115 GDBusConnection *connection,
116 gboolean remote_peer_vanished,
120 GSignondPluginDaemon *daemon = GSIGNOND_PLUGIN_DAEMON (user_data);
122 g_signal_handlers_disconnect_by_func (connection, _on_connection_closed,
124 DBG("dbus connection(%p) closed (peer vanished : %d)", connection,
125 remote_peer_vanished);
127 DBG("...reason : %s", error->message);
129 g_object_unref (daemon);
133 _handle_cancel_from_dbus (
134 GSignondPluginDaemon *self,
135 GDBusMethodInvocation *invocation,
139 g_return_val_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self), FALSE);
140 gsignond_dbus_remote_plugin_complete_cancel (self->priv->dbus_remote_plugin,
143 gsignond_plugin_cancel (self->priv->plugin);
148 _handle_request_from_dbus (
149 GSignondPluginDaemon *self,
150 GDBusMethodInvocation *invocation,
151 const GVariant *session_data,
155 g_return_val_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self), FALSE);
157 gsignond_dbus_remote_plugin_complete_request (
158 self->priv->dbus_remote_plugin, invocation);
160 GSignondSessionData *data = (GSignondSessionData *)
161 gsignond_dictionary_new_from_variant ((GVariant *)session_data);
162 gsignond_plugin_request (self->priv->plugin, data);
163 gsignond_dictionary_unref (data);
168 _handle_response_final_from_plugin (
169 GSignondPluginDaemon *self,
170 GSignondSessionData *session_data,
174 _handle_request_initial_from_dbus (
175 GSignondPluginDaemon *self,
176 GDBusMethodInvocation *invocation,
177 const GVariant *session_data,
178 const GVariant *identity_method_cache,
179 const gchar *mechanism,
183 g_return_val_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self), FALSE);
185 gsignond_dbus_remote_plugin_complete_request_initial (
186 self->priv->dbus_remote_plugin, invocation);
188 GSignondSessionData *data = (GSignondSessionData *)
189 gsignond_dictionary_new_from_variant ((GVariant *)session_data);
190 GSignondSessionData *cache =
191 gsignond_dictionary_new_from_variant ((GVariant *)identity_method_cache);
192 gsignond_plugin_request_initial (self->priv->plugin, data, cache, mechanism);
193 gsignond_dictionary_unref (data);
194 gsignond_dictionary_unref (cache);
200 _handle_user_action_finished_from_dbus (
201 GSignondPluginDaemon *self,
202 GDBusMethodInvocation *invocation,
203 const GVariant *ui_data,
207 g_return_val_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self), FALSE);
209 gsignond_dbus_remote_plugin_complete_user_action_finished (
210 self->priv->dbus_remote_plugin, invocation);
212 GSignondSignonuiData *data = (GSignondSignonuiData *)
213 gsignond_dictionary_new_from_variant ((GVariant *)ui_data);
214 gsignond_plugin_user_action_finished (self->priv->plugin, data);
215 gsignond_dictionary_unref (data);
220 _handle_refresh_from_dbus (
221 GSignondPluginDaemon *self,
222 GDBusMethodInvocation *invocation,
223 const GVariant *ui_data,
227 g_return_val_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self), FALSE);
229 gsignond_dbus_remote_plugin_complete_refresh (
230 self->priv->dbus_remote_plugin, invocation);
232 GSignondSignonuiData *data = (GSignondSignonuiData *)
233 gsignond_dictionary_new_from_variant ((GVariant *)ui_data);
234 gsignond_plugin_refresh (self->priv->plugin, data);
235 gsignond_dictionary_unref (data);
240 _handle_get_info_from_dbus (
241 GSignondPluginDaemon *self,
242 GDBusMethodInvocation *invocation,
246 g_return_val_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self), FALSE);
248 gchar **mechanisms = NULL;
250 g_object_get (self->priv->plugin, "type", &type, "mechanisms", &mechanisms,
252 gsignond_dbus_remote_plugin_complete_get_info (
253 self->priv->dbus_remote_plugin, invocation, (const gchar*)type,
254 (const gchar *const *)mechanisms);
256 g_strfreev (mechanisms);
261 _handle_response_from_plugin (
262 GSignondPluginDaemon *self,
263 GSignondSessionData *session_data,
267 g_return_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self));
269 GVariant *data = gsignond_dictionary_to_variant (
270 (GSignondDictionary *)session_data);
271 gsignond_dbus_remote_plugin_emit_response (self->priv->dbus_remote_plugin,
276 _handle_response_final_from_plugin (
277 GSignondPluginDaemon *self,
278 GSignondSessionData *session_data,
282 g_return_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self));
284 GVariant *data = gsignond_dictionary_to_variant (
285 (GSignondDictionary *)session_data);
286 gsignond_dbus_remote_plugin_emit_response_final (
287 self->priv->dbus_remote_plugin, data);
291 _handle_store_from_plugin (
292 GSignondPluginDaemon *self,
293 GSignondSessionData *session_data,
297 g_return_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self));
299 GVariant *data = gsignond_dictionary_to_variant (
300 (GSignondDictionary *)session_data);
301 gsignond_dbus_remote_plugin_emit_store (self->priv->dbus_remote_plugin,
306 _handle_error_from_plugin (
307 GSignondPluginDaemon *self,
312 g_return_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self));
314 GVariant *error = gsignond_error_to_variant (gerror);
315 gsignond_dbus_remote_plugin_emit_error (self->priv->dbus_remote_plugin,
320 _handle_user_action_required_from_plugin (
321 GSignondPluginDaemon *self,
322 GSignondSignonuiData *ui_data,
326 g_return_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self));
328 GVariant *data = gsignond_dictionary_to_variant (ui_data);
329 gsignond_dbus_remote_plugin_emit_user_action_required (
330 self->priv->dbus_remote_plugin, data);
334 _handle_refreshed_from_plugin(
335 GSignondPluginDaemon *self,
336 GSignondSignonuiData *ui_data,
340 g_return_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self));
342 GVariant *data = gsignond_dictionary_to_variant (ui_data);
343 gsignond_dbus_remote_plugin_emit_refreshed (self->priv->dbus_remote_plugin,
348 _handle_status_changed_from_plugin (
349 GSignondPluginDaemon *self,
350 GSignondPluginState status,
355 g_return_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self));
357 gsignond_dbus_remote_plugin_emit_status_changed (
358 self->priv->dbus_remote_plugin, (gint)status,
359 (const gchar *)message);
362 GSignondPluginDaemon *
363 gsignond_plugin_daemon_new (
364 const gchar* filename,
365 const gchar* plugin_type,
369 GError *error = NULL;
370 GSignondPipeStream *stream = NULL;
372 g_return_val_if_fail (filename != NULL && plugin_type != NULL, NULL);
374 GSignondPluginDaemon *daemon = GSIGNOND_PLUGIN_DAEMON (g_object_new (
375 GSIGNOND_TYPE_PLUGIN_DAEMON, NULL));
378 daemon->priv->plugin = gsignond_load_plugin_with_filename (
379 (gchar *)plugin_type, (gchar *)filename);
380 if (!daemon->priv->plugin) {
381 DBG ("failed to load plugin");
382 g_object_unref (daemon);
386 daemon->priv->plugin_type = g_strdup (plugin_type);
388 /* Create dbus connection */
389 stream = gsignond_pipe_stream_new (in_fd, out_fd, TRUE);
390 daemon->priv->connection = g_dbus_connection_new_sync (G_IO_STREAM (stream),
391 NULL, G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING, NULL, NULL,
393 g_object_unref (stream);
395 /* Create dbus object */
396 daemon->priv->dbus_remote_plugin =
397 gsignond_dbus_remote_plugin_skeleton_new ();
399 g_dbus_interface_skeleton_export (
400 G_DBUS_INTERFACE_SKELETON(daemon->priv->dbus_remote_plugin),
401 daemon->priv->connection, GSIGNOND_PLUGIN_OBJECTPATH, &error);
403 DBG ("failed to register object: %s", error->message);
404 g_error_free (error);
405 g_object_unref (daemon);
408 DBG("Started plugin daemon '%p' at path '%s' on conneciton '%p'",
409 daemon, GSIGNOND_PLUGIN_OBJECTPATH, daemon->priv->connection);
411 /* Connect dbus remote plugin signals to handlers */
412 g_signal_connect_swapped (daemon->priv->dbus_remote_plugin,
413 "handle-cancel", G_CALLBACK (_handle_cancel_from_dbus), daemon);
414 g_signal_connect_swapped (daemon->priv->dbus_remote_plugin,
415 "handle-request", G_CALLBACK(_handle_request_from_dbus), daemon);
416 g_signal_connect_swapped (daemon->priv->dbus_remote_plugin,
417 "handle-request-initial",
418 G_CALLBACK(_handle_request_initial_from_dbus), daemon);
419 g_signal_connect_swapped (daemon->priv->dbus_remote_plugin,
420 "handle-user-action-finished",
421 G_CALLBACK(_handle_user_action_finished_from_dbus), daemon);
422 g_signal_connect_swapped (daemon->priv->dbus_remote_plugin,
423 "handle-refresh", G_CALLBACK(_handle_refresh_from_dbus), daemon);
424 g_signal_connect_swapped (daemon->priv->dbus_remote_plugin,
425 "handle-get-info", G_CALLBACK(_handle_get_info_from_dbus), daemon);
427 /* Connect plugin signals to handlers */
428 g_signal_connect_swapped (daemon->priv->plugin, "response",
429 G_CALLBACK (_handle_response_from_plugin), daemon);
430 g_signal_connect_swapped (daemon->priv->plugin, "response-final",
431 G_CALLBACK(_handle_response_final_from_plugin), daemon);
432 g_signal_connect_swapped (daemon->priv->plugin, "store",
433 G_CALLBACK(_handle_store_from_plugin), daemon);
434 g_signal_connect_swapped (daemon->priv->plugin, "error",
435 G_CALLBACK(_handle_error_from_plugin), daemon);
436 g_signal_connect_swapped (daemon->priv->plugin, "user-action-required",
437 G_CALLBACK(_handle_user_action_required_from_plugin), daemon);
438 g_signal_connect_swapped (daemon->priv->plugin, "refreshed",
439 G_CALLBACK(_handle_refreshed_from_plugin), daemon);
440 g_signal_connect_swapped (daemon->priv->plugin, "status-changed",
441 G_CALLBACK(_handle_status_changed_from_plugin), daemon);
443 g_signal_connect (daemon->priv->connection, "closed",
444 G_CALLBACK(_on_connection_closed), daemon);
446 g_dbus_connection_start_message_processing (daemon->priv->connection);