11e6fc73c1547236fba6b7f9a1a7a1b24a432464
[profile/ivi/gsignond.git] / src / daemon / plugins / plugind / gsignond-plugin-daemon.c
1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 /*
4  * This file is part of gsignond
5  *
6  * Copyright (C) 2013 Intel Corporation.
7  *
8  * Contact: Imran Zaman <imran.zaman@intel.com>
9  *
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.
14  *
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.
19  *
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
23  * 02110-1301 USA
24  */
25
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"
34
35 struct _GSignondPluginDaemonPrivate
36 {
37     GDBusConnection   *connection;
38     GSignondDbusRemotePlugin *dbus_remote_plugin;
39     GSignondPlugin *plugin;
40     gchar *plugin_type;
41 };
42
43 G_DEFINE_TYPE (GSignondPluginDaemon, gsignond_plugin_daemon, G_TYPE_OBJECT)
44
45
46 #define GSIGNOND_PLUGIN_DAEMON_GET_PRIV(obj) \
47     G_TYPE_INSTANCE_GET_PRIVATE ((obj), GSIGNOND_TYPE_PLUGIN_DAEMON,\
48             GSignondPluginDaemonPrivate)
49
50 static void
51 _dispose (GObject *object)
52 {
53     GSignondPluginDaemon *self = GSIGNOND_PLUGIN_DAEMON (object);
54
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;
60     }
61
62     if (self->priv->connection) {
63         g_object_unref (self->priv->connection);
64         self->priv->connection = NULL;
65     }
66
67     if (self->priv->plugin) {
68         g_object_unref (self->priv->plugin);
69         self->priv->plugin = NULL;
70     }
71
72     G_OBJECT_CLASS (gsignond_plugin_daemon_parent_class)->dispose (object);
73 }
74
75 static void
76 _finalize (GObject *object)
77 {
78     GSignondPluginDaemon *self = GSIGNOND_PLUGIN_DAEMON (object);
79
80     if (self->priv->plugin_type) {
81         g_free (self->priv->plugin_type);
82         self->priv->plugin_type = NULL;
83     }
84
85     G_OBJECT_CLASS (gsignond_plugin_daemon_parent_class)->finalize (object);
86 }
87
88 static void
89 gsignond_plugin_daemon_class_init (
90         GSignondPluginDaemonClass *klass)
91 {
92     GObjectClass* object_class = G_OBJECT_CLASS (klass);
93
94     g_type_class_add_private (object_class, sizeof (
95             GSignondPluginDaemonPrivate));
96
97     object_class->dispose = _dispose;
98     object_class->finalize = _finalize;
99
100 }
101
102 static void
103 gsignond_plugin_daemon_init (
104         GSignondPluginDaemon *self)
105 {
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;
111 }
112
113 static void
114 _on_connection_closed (
115         GDBusConnection *connection,
116         gboolean         remote_peer_vanished,
117         GError          *error,
118         gpointer         user_data)
119 {
120     GSignondPluginDaemon *daemon = GSIGNOND_PLUGIN_DAEMON (user_data);
121
122     g_signal_handlers_disconnect_by_func (connection, _on_connection_closed,
123             user_data);
124     DBG("dbus connection(%p) closed (peer vanished : %d)", connection,
125             remote_peer_vanished);
126     if (error) {
127        DBG("...reason : %s", error->message);
128     }
129     g_object_unref (daemon);
130 }
131
132 static gboolean
133 _handle_cancel_from_dbus (
134         GSignondPluginDaemon *self,
135         GDBusMethodInvocation *invocation,
136         gpointer user_data)
137 {
138     DBG ("");
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,
141             invocation);
142
143     gsignond_plugin_cancel (self->priv->plugin);
144     return TRUE;
145 }
146
147 static gboolean
148 _handle_request_from_dbus (
149         GSignondPluginDaemon *self,
150         GDBusMethodInvocation *invocation,
151         const GVariant *session_data,
152         gpointer user_data)
153 {
154     DBG ("");
155     g_return_val_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self), FALSE);
156
157     gsignond_dbus_remote_plugin_complete_request (
158             self->priv->dbus_remote_plugin, invocation);
159
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);
164     return TRUE;
165 }
166
167 static void
168 _handle_response_final_from_plugin (
169         GSignondPluginDaemon *self,
170         GSignondSessionData *session_data,
171         gpointer user_data);
172
173 static gboolean
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,
180         gpointer user_data)
181 {
182     DBG ("");
183     g_return_val_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self), FALSE);
184
185     gsignond_dbus_remote_plugin_complete_request_initial (
186             self->priv->dbus_remote_plugin, invocation);
187
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);
195
196     return TRUE;
197 }
198
199 static gboolean
200 _handle_user_action_finished_from_dbus (
201         GSignondPluginDaemon *self,
202         GDBusMethodInvocation *invocation,
203         const GVariant *ui_data,
204         gpointer user_data)
205 {
206     DBG ("");
207     g_return_val_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self), FALSE);
208
209     gsignond_dbus_remote_plugin_complete_user_action_finished (
210             self->priv->dbus_remote_plugin, invocation);
211
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);
216     return TRUE;
217 }
218
219 static gboolean
220 _handle_refresh_from_dbus (
221         GSignondPluginDaemon *self,
222         GDBusMethodInvocation *invocation,
223         const GVariant *ui_data,
224         gpointer user_data)
225 {
226     DBG ("");
227     g_return_val_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self), FALSE);
228
229     gsignond_dbus_remote_plugin_complete_refresh (
230             self->priv->dbus_remote_plugin, invocation);
231
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);
236     return TRUE;
237 }
238
239 static gboolean
240 _handle_get_info_from_dbus (
241         GSignondPluginDaemon *self,
242         GDBusMethodInvocation *invocation,
243         gpointer user_data)
244 {
245     DBG ("");
246     g_return_val_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self), FALSE);
247     gchar *type = NULL;
248     gchar **mechanisms = NULL;
249
250     g_object_get (self->priv->plugin, "type", &type, "mechanisms", &mechanisms,
251             NULL);
252     gsignond_dbus_remote_plugin_complete_get_info (
253             self->priv->dbus_remote_plugin, invocation, (const gchar*)type,
254             (const gchar *const *)mechanisms);
255     g_free (type);
256     g_strfreev (mechanisms);
257     return TRUE;
258 }
259
260 static void
261 _handle_response_from_plugin (
262         GSignondPluginDaemon *self,
263         GSignondSessionData *session_data,
264         gpointer user_data)
265 {
266     DBG ("");
267     g_return_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self));
268
269     GVariant *data = gsignond_dictionary_to_variant (
270             (GSignondDictionary *)session_data);
271     gsignond_dbus_remote_plugin_emit_response (self->priv->dbus_remote_plugin,
272             data);
273 }
274
275 static void
276 _handle_response_final_from_plugin (
277         GSignondPluginDaemon *self,
278         GSignondSessionData *session_data,
279         gpointer user_data)
280 {
281     DBG ("");
282     g_return_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self));
283
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);
288 }
289
290 static void
291 _handle_store_from_plugin (
292         GSignondPluginDaemon *self,
293         GSignondSessionData *session_data,
294         gpointer user_data)
295 {
296     DBG ("");
297     g_return_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self));
298
299     GVariant *data = gsignond_dictionary_to_variant (
300             (GSignondDictionary *)session_data);
301     gsignond_dbus_remote_plugin_emit_store (self->priv->dbus_remote_plugin,
302             data);
303 }
304
305 static void
306 _handle_error_from_plugin (
307         GSignondPluginDaemon *self,
308         GError *gerror,
309         gpointer user_data)
310 {
311     DBG ("");
312     g_return_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self));
313
314     GVariant *error = gsignond_error_to_variant (gerror);
315     gsignond_dbus_remote_plugin_emit_error (self->priv->dbus_remote_plugin,
316             error);
317 }
318
319 static void
320 _handle_user_action_required_from_plugin (
321         GSignondPluginDaemon *self,
322         GSignondSignonuiData *ui_data,
323         gpointer user_data)
324 {
325     DBG ("");
326     g_return_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self));
327
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);
331 }
332
333 static void
334 _handle_refreshed_from_plugin(
335         GSignondPluginDaemon *self,
336         GSignondSignonuiData *ui_data,
337         gpointer user_data)
338 {
339     DBG ("");
340     g_return_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self));
341
342     GVariant *data = gsignond_dictionary_to_variant (ui_data);
343     gsignond_dbus_remote_plugin_emit_refreshed (self->priv->dbus_remote_plugin,
344             data);
345 }
346
347 static void
348 _handle_status_changed_from_plugin (
349         GSignondPluginDaemon *self,
350         GSignondPluginState status,
351         gchar *message,
352         gpointer user_data)
353 {
354     DBG ("");
355     g_return_if_fail (self && GSIGNOND_IS_PLUGIN_DAEMON (self));
356
357     gsignond_dbus_remote_plugin_emit_status_changed (
358             self->priv->dbus_remote_plugin, (gint)status,
359             (const gchar *)message);
360 }
361
362 GSignondPluginDaemon *
363 gsignond_plugin_daemon_new (
364         const gchar* filename,
365         const gchar* plugin_type,
366         gint in_fd,
367         gint out_fd)
368 {
369     GError *error = NULL;
370     GSignondPipeStream *stream = NULL;
371
372     g_return_val_if_fail (filename != NULL && plugin_type != NULL, NULL);
373
374     GSignondPluginDaemon *daemon = GSIGNOND_PLUGIN_DAEMON (g_object_new (
375             GSIGNOND_TYPE_PLUGIN_DAEMON, NULL));
376
377     /* Load plugin */
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);
383         return NULL;
384     }
385
386     daemon->priv->plugin_type = g_strdup (plugin_type);
387
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,
392             NULL);
393     g_object_unref (stream);
394
395     /* Create dbus object */
396     daemon->priv->dbus_remote_plugin =
397             gsignond_dbus_remote_plugin_skeleton_new ();
398
399     g_dbus_interface_skeleton_export (
400                 G_DBUS_INTERFACE_SKELETON(daemon->priv->dbus_remote_plugin),
401                 daemon->priv->connection, GSIGNOND_PLUGIN_OBJECTPATH, &error);
402     if (error) {
403         DBG ("failed to register object: %s", error->message);
404         g_error_free (error);
405         g_object_unref (daemon);
406         return NULL;
407     }
408     DBG("Started plugin daemon '%p' at path '%s' on conneciton '%p'",
409             daemon, GSIGNOND_PLUGIN_OBJECTPATH, daemon->priv->connection);
410
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);
426
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);
442
443     g_signal_connect (daemon->priv->connection, "closed",
444             G_CALLBACK(_on_connection_closed), daemon);
445
446     g_dbus_connection_start_message_processing (daemon->priv->connection);
447
448     return daemon;
449 }
450