daemon: fixed issue in registring more than one ports by a client.
[profile/ivi/message-port.git] / daemon / dbus-service.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  * Copyright (C) 2013 Intel Corporation.
5  *
6  * Contact: Amarnath Valluri <amarnath.valluri@linux.intel.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  */
23
24 #include "dbus-service.h"
25 #include "common/dbus-service-glue.h"
26 #include "common/dbus-error.h"
27 #include "common/log.h"
28 #include "manager.h"
29 #include "utils.h"
30
31 G_DEFINE_TYPE (MsgPortDbusService, msgport_dbus_service, G_TYPE_OBJECT)
32
33 #define MSGPORT_DBUS_SERVICE_GET_PRIV(obj) \
34     G_TYPE_INSTANCE_GET_PRIVATE ((obj), MSGPORT_TYPE_DBUS_SERVICE, MsgPortDbusServicePrivate)
35
36 struct _MsgPortDbusServicePrivate {
37     guint                   id;
38     MsgPortDbusGlueService *dbus_skeleton;
39     MsgPortDbusManager     *owner;
40     gchar                  *port_name;
41     gboolean                is_trusted;
42 };
43
44
45 static void
46 _dbus_service_finalize (GObject *self)
47 {
48     MsgPortDbusService *dbus_service = MSGPORT_DBUS_SERVICE (self);
49
50     G_OBJECT_CLASS (msgport_dbus_service_parent_class)->finalize (self);
51 }
52
53 static void
54 _dbus_service_dispose (GObject *self)
55 {
56     MsgPortDbusService *dbus_service = MSGPORT_DBUS_SERVICE (self);
57     DBG ("Unregistering service '%s'", dbus_service->priv->port_name);
58     if (dbus_service->priv->dbus_skeleton) {
59         g_dbus_interface_skeleton_unexport (
60                 G_DBUS_INTERFACE_SKELETON (dbus_service->priv->dbus_skeleton));
61         g_clear_object (&dbus_service->priv->dbus_skeleton);
62     }
63
64     G_OBJECT_CLASS (msgport_dbus_service_parent_class)->dispose (self);
65 }
66
67
68 static gboolean
69 _dbus_service_handle_send_message (
70     MsgPortDbusService    *dbus_service,
71     GDBusMethodInvocation *invocation,
72     guint                   remote_service_id,
73     GVariant              *data,
74     gpointer               userdata)
75 {
76     MsgPortDbusService *peer_dbus_service = NULL;
77     MsgPortManager *manager = NULL;
78     GError *error;
79
80     msgport_return_val_if_fail_with_error (dbus_service &&  MSGPORT_IS_DBUS_SERVICE (dbus_service), FALSE, &error);
81
82     DBG ("Send Message rquest on service %p to remote service id : %d", dbus_service, remote_service_id);
83     manager = msgport_dbus_manager_get_manager (dbus_service->priv->owner);
84     peer_dbus_service = msgport_manager_get_service_by_id (manager, remote_service_id, &error);
85
86     if (peer_dbus_service) {
87         if (msgport_dbus_service_send_message (peer_dbus_service, data,
88                 msgport_dbus_service_get_app_id (dbus_service),
89                 dbus_service->priv->port_name,
90                 dbus_service->priv->is_trusted, &error)) {
91             msgport_dbus_glue_service_complete_send_message (
92                     dbus_service->priv->dbus_skeleton, invocation);
93
94             return TRUE;
95         }
96     }
97     
98     if (!error) error = msgport_error_unknown_new ();
99     g_dbus_method_invocation_take_error (invocation, error);
100
101     return TRUE;
102 }
103
104 static gboolean
105 _dbus_service_handle_unregister (
106     MsgPortDbusService    *dbus_service,
107     GDBusMethodInvocation *invocation,
108     gpointer               userdata)
109 {
110     GError *error = NULL;
111     msgport_return_val_if_fail_with_error (dbus_service && MSGPORT_IS_DBUS_SERVICE (dbus_service), FALSE, &error);
112
113     /* FIXME unregister */
114     return TRUE;
115 }
116
117 static void
118 msgport_dbus_service_init (MsgPortDbusService *self)
119 {
120     MsgPortDbusServicePrivate *priv = MSGPORT_DBUS_SERVICE_GET_PRIV (self);
121
122     priv->dbus_skeleton = msgport_dbus_glue_service_skeleton_new ();
123     priv->owner = NULL;
124     priv->id = 0;
125     priv->port_name = NULL;
126
127     g_signal_connect_swapped (priv->dbus_skeleton, "handle-send-message",
128                 G_CALLBACK (_dbus_service_handle_send_message), (gpointer)self);
129     g_signal_connect_swapped (priv->dbus_skeleton, "handle-unregister",
130                 G_CALLBACK (_dbus_service_handle_unregister), (gpointer)self);
131
132     self->priv = priv;
133 }
134
135 static void
136 msgport_dbus_service_class_init (MsgPortDbusServiceClass *klass)
137 {
138     GObjectClass *gklass = G_OBJECT_CLASS(klass);
139
140     g_type_class_add_private (klass, sizeof(MsgPortDbusServicePrivate));
141
142     gklass->finalize = _dbus_service_finalize;
143     gklass->dispose = _dbus_service_dispose;
144 }
145
146 MsgPortDbusService *
147 msgport_dbus_service_new (MsgPortDbusManager *owner, const gchar *name, gboolean is_trusted, GError **error)
148 {
149     static guint object_conter = 0;
150
151     MsgPortDbusService *dbus_service = NULL;
152     GDBusConnection *connection = NULL;
153     gchar *object_path = 0;
154
155     msgport_return_val_if_fail_with_error (owner && MSGPORT_IS_DBUS_MANAGER (owner), NULL, error);
156     msgport_return_val_if_fail_with_error (name && name[0], NULL, error);
157
158     connection = msgport_dbus_manager_get_connection (owner),
159     dbus_service = MSGPORT_DBUS_SERVICE (g_object_new (MSGPORT_TYPE_DBUS_SERVICE, NULL));
160     if (!dbus_service) {
161         if (error) *error = msgport_error_no_memory_new ();
162         return NULL;
163     }
164     dbus_service->priv->owner = owner;
165     dbus_service->priv->id = object_conter + 1;
166     dbus_service->priv->port_name = g_strdup (name);
167     dbus_service->priv->is_trusted = is_trusted;
168
169     /* FIXME: better way of path creation */
170     object_path = g_strdup_printf ("/%u", dbus_service->priv->id); 
171     if (!g_dbus_interface_skeleton_export (
172             G_DBUS_INTERFACE_SKELETON (dbus_service->priv->dbus_skeleton),
173             connection,
174             object_path,
175             error)) {
176         g_print ("Failed to export dbus object on connection %p : %s",
177                     connection, error ? (*error)->message : "");
178         g_object_unref (dbus_service);
179         g_free (object_path);
180         object_conter--;
181
182         return NULL;
183     }
184     g_free (object_path);
185
186     /* set dbus-properties */
187     g_object_set (G_OBJECT (dbus_service->priv->dbus_skeleton), 
188                             "id", dbus_service->priv->id,
189                             "port-name", dbus_service->priv->port_name,
190                             "is-trusted", dbus_service->priv->is_trusted, NULL);
191
192     ++object_conter;
193     
194     return dbus_service;
195 }
196
197 guint
198 msgport_dbus_service_get_id (MsgPortDbusService *dbus_service)
199 {
200     g_return_val_if_fail (dbus_service && MSGPORT_IS_DBUS_SERVICE (dbus_service), 0);
201
202     return dbus_service->priv->id;
203 }
204
205 const gchar *
206 msgport_dbus_service_get_object_path (MsgPortDbusService *dbus_service)
207 {
208     g_return_val_if_fail (dbus_service && MSGPORT_IS_DBUS_SERVICE (dbus_service), NULL);
209
210     return g_dbus_interface_skeleton_get_object_path (
211         G_DBUS_INTERFACE_SKELETON (dbus_service->priv->dbus_skeleton)) ;
212 }
213
214 GDBusConnection *
215 msgport_dbus_service_get_connection (MsgPortDbusService *dbus_service)
216 {
217     g_return_val_if_fail (dbus_service && MSGPORT_IS_DBUS_SERVICE (dbus_service), NULL);
218
219     return msgport_dbus_manager_get_connection (dbus_service->priv->owner);
220 }
221
222 MsgPortDbusManager *
223 msgport_dbus_service_get_owner (MsgPortDbusService *dbus_service)
224 {
225     g_return_val_if_fail (dbus_service && MSGPORT_IS_DBUS_SERVICE (dbus_service), NULL);
226
227     return dbus_service->priv->owner;
228 }
229
230 const gchar *
231 msgport_dbus_service_get_port_name (MsgPortDbusService *dbus_service)
232 {
233     g_return_val_if_fail (dbus_service && MSGPORT_IS_DBUS_SERVICE (dbus_service), NULL);
234
235     return (const gchar *)dbus_service->priv->port_name;
236 }
237
238 const gchar *
239 msgport_dbus_service_get_app_id (MsgPortDbusService *dbus_service)
240 {
241     g_return_val_if_fail (dbus_service && MSGPORT_IS_DBUS_SERVICE (dbus_service), NULL);
242
243     return msgport_dbus_manager_get_app_id (dbus_service->priv->owner);
244 }
245
246 gboolean
247 msgport_dbus_service_get_is_trusted (MsgPortDbusService *dbus_service)
248 {
249     g_return_val_if_fail (dbus_service && MSGPORT_IS_DBUS_SERVICE (dbus_service), FALSE);
250
251     return dbus_service->priv->is_trusted;
252 }
253
254 gboolean
255 msgport_dbus_service_send_message (
256     MsgPortDbusService *dbus_service,
257     GVariant *data,
258     const gchar *r_app_id,
259     const gchar *r_port,
260     gboolean r_is_trusted,
261     GError **error)
262 {
263     msgport_return_val_if_fail_with_error (dbus_service && MSGPORT_IS_DBUS_SERVICE (dbus_service), FALSE, error);
264
265     if (dbus_service->priv->is_trusted &&
266         !msgport_dbus_manager_validate_peer_certificate (dbus_service->priv->owner, r_app_id)) {
267         if (error) *error = msgport_error_certificate_mismatch_new ();
268         return FALSE;
269     }
270
271     DBG ("Sending message to %p from '%s:%s'", dbus_service, r_app_id, r_port);
272     msgport_dbus_glue_service_emit_on_message (dbus_service->priv->dbus_skeleton, data, r_app_id, r_port, r_is_trusted);
273  
274     return TRUE;
275 }
276