c18414f74bfd44e7bf28363764dc13a040a060cf
[platform/core/system/tlm.git] / src / sessiond / tlm-session-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 tlm
5  *
6  * Copyright (C) 2014 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 "common/tlm-log.h"
27 #include "common/tlm-error.h"
28 #include "common/tlm-pipe-stream.h"
29 #include "common/dbus/tlm-dbus-session-gen.h"
30 #include "common/dbus/tlm-dbus-utils.h"
31 #include "common/dbus/tlm-dbus.h"
32 #include "tlm-session-daemon.h"
33 #include "tlm-session.h"
34
35 struct _TlmSessionDaemonPrivate
36 {
37     GDBusConnection *connection;
38     TlmDbusSession *dbus_session;
39     TlmSession *session;
40 };
41
42 G_DEFINE_TYPE (TlmSessionDaemon, tlm_session_daemon, G_TYPE_OBJECT)
43
44
45 #define TLM_SESSION_DAEMON_GET_PRIV(obj) \
46     G_TYPE_INSTANCE_GET_PRIVATE ((obj), TLM_TYPE_SESSION_DAEMON,\
47             TlmSessionDaemonPrivate)
48
49 static void
50 _dispose (GObject *object)
51 {
52     TlmSessionDaemon *self = TLM_SESSION_DAEMON (object);
53     if (self->priv->dbus_session) {
54         g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (
55                 self->priv->dbus_session));
56         g_object_unref (self->priv->dbus_session);
57         self->priv->dbus_session = NULL;
58     }
59
60     if (self->priv->connection) {
61         g_object_unref (self->priv->connection);
62         self->priv->connection = NULL;
63     }
64
65     if (self->priv->session) {
66         g_object_unref (self->priv->session);
67         self->priv->session = NULL;
68     }
69
70     G_OBJECT_CLASS (tlm_session_daemon_parent_class)->dispose (object);
71 }
72
73 static void
74 _finalize (GObject *object)
75 {
76     G_OBJECT_CLASS (tlm_session_daemon_parent_class)->finalize (object);
77 }
78
79 static void
80 tlm_session_daemon_class_init (
81         TlmSessionDaemonClass *klass)
82 {
83     GObjectClass* object_class = G_OBJECT_CLASS (klass);
84
85     g_type_class_add_private (object_class, sizeof (
86             TlmSessionDaemonPrivate));
87
88     object_class->dispose = _dispose;
89     object_class->finalize = _finalize;
90
91 }
92
93 static void
94 tlm_session_daemon_init (
95         TlmSessionDaemon *self)
96 {
97     self->priv = TLM_SESSION_DAEMON_GET_PRIV(self);
98     self->priv->connection = NULL;
99     self->priv->dbus_session = NULL;
100     self->priv->session = NULL;
101 }
102
103 static void
104 _on_connection_closed (
105         GDBusConnection *connection,
106         gboolean         remote_peer_vanished,
107         GError          *error,
108         gpointer         user_data)
109 {
110     TlmSessionDaemon *daemon = TLM_SESSION_DAEMON (user_data);
111
112     g_signal_handlers_disconnect_by_func (connection, _on_connection_closed,
113             user_data);
114     DBG("dbus connection(%p) closed (peer vanished : %d)", connection,
115             remote_peer_vanished);
116     if (error) {
117        DBG("...reason : %s", error->message);
118     }
119     g_object_unref (daemon);
120 }
121
122 static gboolean
123 _handle_session_create_from_dbus (
124         TlmSessionDaemon *self,
125         GDBusMethodInvocation *invocation,
126         const gchar *password,
127         GVariant *environment,
128         gpointer user_data)
129 {
130     g_return_val_if_fail (self && TLM_IS_SESSION_DAEMON (self), FALSE);
131     gchar *seatid = NULL;
132     gchar *service = NULL;
133     gchar *username = NULL;
134     GHashTable *data = NULL;
135
136     tlm_dbus_session_complete_session_create (
137             self->priv->dbus_session, invocation);
138
139     gchar *data_str = g_variant_print(environment, TRUE);
140     DBG("%s", data_str);
141     g_free(data_str);
142
143     data = tlm_dbus_utils_hash_table_from_variant (environment);
144     g_object_get (self->priv->dbus_session, "seatid", &seatid,
145             "username", &username, "service", &service, NULL);
146
147     tlm_session_start (self->priv->session, seatid, service, username,
148             password, data);
149
150     g_hash_table_unref (data);
151     g_free (seatid);
152     g_free (service);
153     g_free (username);
154     return TRUE;
155 }
156
157 static gboolean
158 _handle_session_terminate_from_dbus (
159         TlmSessionDaemon *self,
160         GDBusMethodInvocation *invocation,
161         gpointer user_data)
162 {
163     g_return_val_if_fail (self && TLM_IS_SESSION_DAEMON (self), FALSE);
164
165     tlm_dbus_session_complete_session_terminate (self->priv->dbus_session,
166             invocation);
167
168     tlm_session_terminate (self->priv->session);
169     return TRUE;
170 }
171
172 static void
173 _handle_session_created_from_session (
174         TlmSessionDaemon *self,
175         const gchar *sessionid,
176         gpointer user_data)
177 {
178     g_return_if_fail (self && TLM_IS_SESSION_DAEMON (self));
179
180     DBG ("sessionid: %s", sessionid);
181
182     g_object_set (G_OBJECT (self->priv->dbus_session), "sessionid", sessionid,
183             NULL);
184     tlm_dbus_session_emit_session_created (self->priv->dbus_session, sessionid);
185 }
186
187 static void
188 _handle_session_terminated_from_session (
189         TlmSessionDaemon *self,
190         gpointer user_data)
191 {
192     g_return_if_fail (self && TLM_IS_SESSION_DAEMON (self));
193
194     tlm_dbus_session_emit_session_terminated (self->priv->dbus_session);
195 }
196
197 static void
198 _handle_authenticated_from_session (
199         TlmSessionDaemon *self,
200         gpointer user_data)
201 {
202     g_return_if_fail (self && TLM_IS_SESSION_DAEMON (self));
203
204     tlm_dbus_session_emit_authenticated (self->priv->dbus_session);
205 }
206
207 static void
208 _handle_error_from_session (
209         TlmSessionDaemon *self,
210         GError *gerror,
211         gpointer user_data)
212 {
213     g_return_if_fail (self && TLM_IS_SESSION_DAEMON (self));
214
215     GVariant *error = tlm_error_to_variant (gerror);
216     gchar *data_str = g_variant_print (error, TRUE);
217     DBG("%s", data_str);
218     g_free (data_str);
219
220     tlm_dbus_session_emit_error (self->priv->dbus_session, error);
221 }
222
223 TlmSessionDaemon *
224 tlm_session_daemon_new (
225         gint in_fd,
226         gint out_fd)
227 {
228     GError *error = NULL;
229     TlmPipeStream *stream = NULL;
230
231     TlmSessionDaemon *daemon = TLM_SESSION_DAEMON (g_object_new (
232             TLM_TYPE_SESSION_DAEMON, NULL));
233
234     /* Load session */
235     daemon->priv->session = tlm_session_new ();
236     if (!daemon->priv->session) {
237         DBG ("failed to create session object");
238         g_object_unref (daemon);
239         return NULL;
240     }
241     tlm_log_init(G_LOG_DOMAIN);
242     /* Create dbus connection */
243     stream = tlm_pipe_stream_new (in_fd, out_fd, TRUE);
244     daemon->priv->connection = g_dbus_connection_new_sync (G_IO_STREAM (stream),
245             NULL, G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING, NULL, NULL,
246             NULL);
247     g_object_unref (stream);
248
249     /* Create dbus object */
250     daemon->priv->dbus_session =
251             tlm_dbus_session_skeleton_new ();
252
253     /* Connect dbus remote session signals to handlers */
254     g_signal_connect_swapped (daemon->priv->dbus_session,
255             "handle-session-create", G_CALLBACK (
256                 _handle_session_create_from_dbus), daemon);
257     g_signal_connect_swapped (daemon->priv->dbus_session,
258             "handle-session-terminate", G_CALLBACK(
259                 _handle_session_terminate_from_dbus), daemon);
260
261     /* Connect session signals to handlers */
262     g_signal_connect_swapped (daemon->priv->session, "session-created",
263             G_CALLBACK (_handle_session_created_from_session), daemon);
264     g_signal_connect_swapped (daemon->priv->session, "session-terminated",
265             G_CALLBACK(_handle_session_terminated_from_session), daemon);
266     g_signal_connect_swapped (daemon->priv->session, "authenticated",
267             G_CALLBACK(_handle_authenticated_from_session), daemon);
268     g_signal_connect_swapped (daemon->priv->session, "session-error",
269             G_CALLBACK(_handle_error_from_session), daemon);
270
271     g_signal_connect (daemon->priv->connection, "closed",
272             G_CALLBACK(_on_connection_closed), daemon);
273
274     g_dbus_interface_skeleton_export (
275                 G_DBUS_INTERFACE_SKELETON(daemon->priv->dbus_session),
276                 daemon->priv->connection, TLM_SESSION_OBJECTPATH, &error);
277     if (error) {
278         DBG ("failed to register object: %s", error->message);
279         g_error_free (error);
280         g_object_unref (daemon);
281         return NULL;
282     }
283     DBG("Started session daemon '%p' at path '%s' on connection '%p'",
284             daemon, TLM_SESSION_OBJECTPATH, daemon->priv->connection);
285
286     g_dbus_connection_start_message_processing (daemon->priv->connection);
287
288     return daemon;
289 }