e381cc239e4ecd2c27f9e402a8da0f896893ecee
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-obex-agent.c
1 /*
2  * bluetooth-frwk
3  *
4  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *              http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <dbus/dbus-glib-lowlevel.h>
21 #include <dbus/dbus-glib.h>
22 #include <dbus/dbus.h>
23 #include <glib.h>
24 #include <dlog.h>
25 #include <string.h>
26
27 #include "bluetooth-api.h"
28 #include "bt-service-common.h"
29 #include "bt-service-event.h"
30 #include "bt-service-util.h"
31 #include "bt-service-obex-agent.h"
32 #include "marshal.h"
33 #include "bt-obex-agent-method.h"
34
35 static DBusGConnection *obex_conn = NULL;
36
37 typedef struct {
38         gchar *name;
39         gchar *path;
40
41         /* callback data */
42         gpointer authorize_data;
43         gpointer release_data;
44         gpointer request_data;
45         gpointer progress_data;
46         gpointer complete_data;
47         gpointer error_data;
48
49         /* callback function */
50         bt_obex_authorize_cb authorize_cb;
51         bt_obex_release_cb release_cb;
52         bt_obex_request_cb request_cb;
53         bt_obex_progress_cb progress_cb;
54         bt_obex_complete_cb complete_cb;
55         bt_obex_error_cb error_cb;
56 } bt_obex_agent_info;
57
58 #define BT_OBEX_AGENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
59                                         BT_OBEX_TYPE_AGENT, bt_obex_agent_info))
60
61 G_DEFINE_TYPE(BtObexAgent, bt_obex_agent, G_TYPE_OBJECT)
62
63 gboolean bt_obex_agent_authorize_push(BtObexAgent *agent, const char *path,
64                              DBusGMethodInvocation *context)
65 {
66         bt_obex_agent_info *info;
67         gboolean result;
68
69         info = BT_OBEX_AGENT_GET_PRIVATE(agent);
70
71         if (info == NULL)
72                 goto fail;
73
74         if (info->authorize_cb == NULL)
75                 goto fail;
76
77         result = info->authorize_cb(context, path,
78                                 info->authorize_data);
79
80         return result;
81 fail:
82         dbus_g_method_return(context, "");
83         return FALSE;
84 }
85
86 gboolean bt_obex_agent_request(BtObexAgent *agent, const char *path,
87                                    DBusGMethodInvocation *context)
88 {
89         char *sender;
90         bt_obex_agent_info *info;
91         DBusGProxy *proxy;
92         gboolean result;
93
94         info = BT_OBEX_AGENT_GET_PRIVATE(agent);
95
96         if (info == NULL)
97                 goto fail;
98
99         if (obex_conn == NULL)
100                 goto fail;
101
102         sender = dbus_g_method_get_sender(context);
103
104         BT_DBG("sender %s", sender);
105
106         if (info->name == NULL) {
107                 info->name = sender;
108         } else {
109                 if (g_strcmp0(sender, info->name) != 0) {
110                         g_free(sender);
111                         goto fail;
112                 }
113                 g_free(sender);
114         }
115
116         if (info->request_cb == NULL)
117                 goto fail;
118
119         proxy = dbus_g_proxy_new_for_name(obex_conn, BT_OBEX_SERVICE_NAME,
120                                           path, BT_OBEX_TRANSFER_INTERFACE);
121
122         result = info->request_cb(context, proxy, info->request_data);
123         g_object_unref(proxy);
124
125         return result;
126 fail:
127         BT_ERR("Fail case");
128         dbus_g_method_return(context, "");
129         return FALSE;
130 }
131
132 gboolean bt_obex_agent_progress(BtObexAgent *agent, const char *path,
133                     guint64 transferred, DBusGMethodInvocation *context)
134 {
135         bt_obex_agent_info *info;
136         char *sender;
137         gboolean result;
138         DBusGProxy *proxy;
139
140         info = BT_OBEX_AGENT_GET_PRIVATE(agent);
141
142         if (info == NULL)
143                 goto fail;
144
145         if (obex_conn == NULL)
146                 goto fail;
147
148         sender = dbus_g_method_get_sender(context);
149
150         if (g_strcmp0(sender, info->name) != 0) {
151                 g_free(sender);
152                 goto fail;
153         }
154
155         g_free(sender);
156
157         if (info->progress_cb == NULL)
158                 goto fail;
159
160         proxy = dbus_g_proxy_new_for_name(obex_conn, BT_OBEX_SERVICE_NAME,
161                                           path, BT_OBEX_TRANSFER_INTERFACE);
162
163         result = info->progress_cb(context, proxy, transferred, info->progress_data);
164
165         g_object_unref(proxy);
166
167         return result;
168 fail:
169         BT_ERR("Fail case");
170         dbus_g_method_return(context, "");
171         return FALSE;
172 }
173
174 gboolean bt_obex_agent_error(BtObexAgent *agent, const char *path,
175                          const char *message, DBusGMethodInvocation *context)
176 {
177         bt_obex_agent_info *info;
178         char *sender;
179         DBusGProxy *proxy;
180         gboolean result;
181
182         info = BT_OBEX_AGENT_GET_PRIVATE(agent);
183
184         if (info == NULL)
185                 goto fail;
186
187         if (obex_conn == NULL)
188                 goto fail;
189
190         sender = dbus_g_method_get_sender(context);
191
192         if (g_strcmp0(sender, info->name) != 0) {
193                 g_free(sender);
194                 goto fail;
195         }
196
197         g_free(sender);
198
199         if (info->error_cb == NULL)
200                 goto fail;
201
202         proxy = dbus_g_proxy_new_for_name(obex_conn, BT_OBEX_SERVICE_NAME,
203                                           path, BT_OBEX_TRANSFER_INTERFACE);
204
205         result = info->error_cb(context, proxy, message, info->progress_data);
206
207         g_object_unref(proxy);
208
209         return result;
210 fail:
211         BT_ERR("Fail case");
212         dbus_g_method_return(context, "");
213         return FALSE;
214 }
215
216 gboolean bt_obex_agent_complete(BtObexAgent *agent, const char *path,
217                                     DBusGMethodInvocation *context)
218 {
219         bt_obex_agent_info *info;
220         char *sender;
221         DBusGProxy *proxy;
222         gboolean result;
223
224         info = BT_OBEX_AGENT_GET_PRIVATE(agent);
225
226         if (info == NULL)
227                 goto fail;
228
229         if (obex_conn == NULL)
230                 goto fail;
231
232         sender = dbus_g_method_get_sender(context);
233
234         if (g_strcmp0(sender, info->name) != 0) {
235                 g_free(sender);
236                 goto fail;
237         }
238
239         g_free(sender);
240
241         if (info->complete_cb == NULL)
242                 goto fail;
243
244         proxy = dbus_g_proxy_new_for_name(obex_conn, BT_OBEX_SERVICE_NAME,
245                                           path, BT_OBEX_TRANSFER_INTERFACE);
246
247         result = info->complete_cb(context, proxy, info->complete_data);
248
249         g_object_unref(proxy);
250
251         return result;
252 fail:
253         BT_ERR("Fail case");
254         dbus_g_method_return(context, "");
255         return FALSE;
256 }
257
258 gboolean bt_obex_agent_release(BtObexAgent *agent, DBusGMethodInvocation *context)
259 {
260         bt_obex_agent_info *info;
261         char *sender;
262         gboolean result;
263
264         info = BT_OBEX_AGENT_GET_PRIVATE(agent);
265
266         if (info == NULL)
267                 goto fail;
268
269         sender = dbus_g_method_get_sender(context);
270
271         if (info->name) {
272                 /*In H2 if user denies auth,release will come without request and hence
273                 info->name will be NULL */
274                 if (g_strcmp0(sender, info->name) != 0) {
275                         g_free(sender);
276                         goto fail;
277                 }
278         }
279         g_free(sender);
280
281         if (info->release_cb == NULL)
282                 goto fail;
283
284         result = info->release_cb(context, info->release_data);
285
286         return result;
287 fail:
288         BT_ERR("Fail case");
289         dbus_g_method_return(context, "");
290         return FALSE;
291 }
292
293 static void bt_obex_agent_init(BtObexAgent *agent)
294 {
295         BT_DBG("agent %p", agent);
296 }
297
298 static void bt_obex_agent_finalize(GObject *agent)
299 {
300         bt_obex_agent_info *info;
301
302         info = BT_OBEX_AGENT_GET_PRIVATE(agent);
303
304         if (info) {
305                 g_free(info->path);
306                 g_free(info->name);
307         }
308
309         G_OBJECT_CLASS(bt_obex_agent_parent_class)->finalize(agent);
310 }
311
312 static void bt_obex_agent_class_init(BtObexAgentClass *agent_class)
313 {
314         GObjectClass *object_class;
315         GError *error = NULL;
316
317         object_class = (GObjectClass *)agent_class;
318
319         g_type_class_add_private(agent_class, sizeof(bt_obex_agent_info));
320
321         object_class->finalize = bt_obex_agent_finalize;
322
323         obex_conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
324
325         if (error != NULL) {
326                 BT_ERR("Fail to get dbus: %s", error->message);
327                 g_error_free(error);
328         }
329
330         dbus_g_object_type_install_info(BT_OBEX_TYPE_AGENT,
331                                 &dbus_glib_bt_obex_agent_object_info);
332 }
333
334 BtObexAgent *_bt_obex_agent_new(void)
335 {
336         BtObexAgent *agent;
337
338         agent = BT_OBEX_AGENT(g_object_new(BT_OBEX_TYPE_AGENT, NULL));
339
340         return agent;
341 }
342
343 gboolean _bt_obex_setup(BtObexAgent *agent, const char *path)
344 {
345         bt_obex_agent_info *info;
346         DBusGProxy *proxy;
347         GObject *object;
348
349         info = BT_OBEX_AGENT_GET_PRIVATE(agent);
350
351         retv_if(obex_conn == NULL, FALSE);
352         retv_if(info == NULL, FALSE);
353         retv_if(info->path != NULL, FALSE);
354
355         info->path = g_strdup(path);
356
357         proxy = dbus_g_proxy_new_for_name_owner(obex_conn, BT_OBEX_SERVICE_NAME,
358                                                 BT_OBEX_CLIENT_PATH,
359                                                 BT_OBEX_AGENT_INTERFACE, NULL);
360         g_free(info->name);
361
362         if (proxy != NULL) {
363                 info->name = g_strdup(dbus_g_proxy_get_bus_name(proxy));
364                 g_object_unref(proxy);
365         } else {
366                 info->name = NULL;
367         }
368
369         object = dbus_g_connection_lookup_g_object(obex_conn, info->path);
370         if (object != NULL)
371                 g_object_unref(object);
372
373         dbus_g_connection_register_g_object(obex_conn, info->path, G_OBJECT(agent));
374
375         dbus_g_object_register_marshaller(marshal_VOID__OBJECT_BOOLEAN,
376                                           G_TYPE_NONE, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_BOOLEAN,
377                                           G_TYPE_INVALID);
378
379         dbus_g_object_register_marshaller(marshal_VOID__INT_INT,
380                                           G_TYPE_NONE, G_TYPE_INT, G_TYPE_INT, G_TYPE_INVALID);
381         return TRUE;
382 }
383
384 void _bt_obex_set_authorize_cb(BtObexAgent *agent,
385                          bt_obex_authorize_cb func, gpointer data)
386 {
387         bt_obex_agent_info *info = BT_OBEX_AGENT_GET_PRIVATE(agent);
388
389         info->authorize_cb = func;
390         info->authorize_data = data;
391 }
392
393 void _bt_obex_set_release_cb(BtObexAgent *agent,
394                        bt_obex_release_cb func, gpointer data)
395 {
396         bt_obex_agent_info *info = BT_OBEX_AGENT_GET_PRIVATE(agent);
397
398         info->release_cb = func;
399         info->release_data = data;
400 }
401
402 void _bt_obex_set_request_cb(BtObexAgent *agent,
403                        bt_obex_request_cb func, gpointer data)
404 {
405         bt_obex_agent_info *info = BT_OBEX_AGENT_GET_PRIVATE(agent);
406
407         info->request_cb = func;
408         info->request_data = data;
409 }
410
411 void _bt_obex_set_progress_cb(BtObexAgent *agent,
412                         bt_obex_progress_cb func, gpointer data)
413 {
414         bt_obex_agent_info *info = BT_OBEX_AGENT_GET_PRIVATE(agent);
415
416         info->progress_cb = func;
417         info->progress_data = data;
418 }
419
420 void _bt_obex_set_complete_cb(BtObexAgent *agent,
421                         bt_obex_complete_cb func, gpointer data)
422 {
423         bt_obex_agent_info *info = BT_OBEX_AGENT_GET_PRIVATE(agent);
424
425         info->complete_cb = func;
426         info->complete_data = data;
427 }
428
429 void _bt_obex_set_error_cb(BtObexAgent *agent,
430                         bt_obex_error_cb func, gpointer data)
431 {
432         bt_obex_agent_info *info = BT_OBEX_AGENT_GET_PRIVATE(agent);
433
434         info->error_cb = func;
435         info->error_data = data;
436 }