Merge the code from tizen_2.4
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-obex-agent.c
1 /*
2  * Bluetooth-frwk
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:  Hocheol Seo <hocheol.seo@samsung.com>
7  *               Girishashok Joshi <girish.joshi@samsung.com>
8  *               Chanyeol Park <chanyeol.park@samsung.com>
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *              http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  */
23
24 #include <glib.h>
25 #include <dlog.h>
26 #include <string.h>
27 #include <gio/gio.h>
28
29 #include "bluetooth-api.h"
30 #include "bt-service-common.h"
31 #include "bt-service-event.h"
32 #include "bt-service-util.h"
33 #include "bt-service-obex-agent.h"
34 #include "marshal.h"
35
36 static GDBusConnection *conn = NULL;
37 static GSList *obex_agent_list = NULL;
38
39 typedef struct {
40         gchar *name;
41         gchar *path;
42
43         int openobex_id;
44         int obex_agent_id;
45
46         /* callback data */
47         gpointer authorize_data;
48         gpointer release_data;
49         gpointer request_data;
50         gpointer progress_data;
51         gpointer complete_data;
52         gpointer error_data;
53
54         /* callback function */
55         bt_obex_authorize_cb authorize_cb;
56         bt_obex_release_cb release_cb;
57         bt_obex_request_cb request_cb;
58         bt_obex_progress_cb progress_cb;
59         bt_obex_complete_cb complete_cb;
60         bt_obex_error_cb error_cb;
61 } bt_obex_agent_info;
62
63 static void __new_connection_method(GDBusConnection *connection,
64                                             const gchar *sender,
65                                             const gchar *object_path,
66                                             const gchar *interface_name,
67                                             const gchar *method_name,
68                                             GVariant *parameters,
69                                             GDBusMethodInvocation *invocation,
70                                             gpointer user_data);
71 static const GDBusInterfaceVTable method_table = {
72         __new_connection_method,
73         NULL,
74         NULL,
75 };
76
77 static const gchar obex_service_agent_xml1[] =
78 "<node name='/'>"
79 "  <interface name='org.openobex.Agent'>"
80 "    <method name='Request'>"
81 "      <annotation name='org.freedesktop.DBus.GLib.Async' value=''/>"
82 "      <arg type='o' name='transfer'/>"
83 "     <arg type='s' name='name' direction='out'/>"
84 "    </method>"
85 "    <method name='Progress'>"
86 "      <annotation name='org.freedesktop.DBus.GLib.Async' value=''/>"
87 "      <arg type='o' name='transfer'/>"
88 "      <arg type='t' name='transferred'/>"
89 "    </method>"
90 "    <method name='Complete'>"
91 "      <annotation name='org.freedesktop.DBus.GLib.Async' value=''/>"
92 "      <arg type='o' name='transfer'/>"
93  "   </method>"
94 "    <method name='Release'>"
95 "      <annotation name='org.freedesktop.DBus.GLib.Async' value=''/>"
96 "    </method>"
97 "    <method name='Error'>"
98 "      <annotation name='org.freedesktop.DBus.GLib.Async' value=''/>"
99 "      <arg type='o' name='transfer'/>"
100 "      <arg type='s' name='message'/>"
101 "    </method>"
102 "    <method name='Authorize'>"
103 "       <annotation name='org.freedesktop.DBus.GLib.Async' value=''/>"
104 "               <arg type='o' name='objpath'/>"
105 "               <arg type='s' name='bdaddress'/>"
106 "               <arg type='s' name='name'/>"
107 "               <arg type='s' name='type'/>"
108 "               <arg type='i' name='length'/>"
109 "               <arg type='i' name='time'/>"
110 "               <arg type='s' name='filepath' direction='out'/>"
111 "       </method>"
112 "  </interface>"
113 "</node>";
114
115 static const gchar obex_service_agent_xml2[] =
116 "<node name='/'>"
117 "  <interface name='org.bluez.obex.Agent1'>"
118 "    <method name='AuthorizePush'>"
119 "    <annotation name='org.freedesktop.DBus.GLib.Async' value=''/>"
120 "        <arg type='o' name='objpath'/>"
121 "        <arg type='s' name='filepath' direction='out'/>"
122 "    </method>"
123 "  </interface>"
124 "</node>";
125
126 static bt_obex_agent_info *__find_obex_agent_info(char *path)
127 {
128         GSList *l;
129
130         for (l = obex_agent_list; l != NULL; l = l->next) {
131                 bt_obex_agent_info *info = l->data;
132
133                 if (g_strcmp0(info->path, path) == 0)
134                         return info;
135         }
136
137         return NULL;
138 }
139
140
141 static void __new_connection_method(GDBusConnection *connection,
142                                             const gchar *sender,
143                                             const gchar *object_path,
144                                             const gchar *interface_name,
145                                             const gchar *method_name,
146                                             GVariant *parameters,
147                                             GDBusMethodInvocation *invocation,
148                                             gpointer user_data)
149 {
150         BT_DBG("method_name %s", method_name);
151         if (g_strcmp0(method_name, "AuthorizePush") == 0) {
152                 bt_obex_agent_info *info;
153                 char *path = NULL;
154                 info = __find_obex_agent_info((char *)object_path);
155
156                 if (info == NULL)
157                         goto fail;
158
159                 if (info->authorize_cb == NULL)
160                         goto fail;
161
162                 g_variant_get(parameters, "(&o)", &path);
163
164                 info->authorize_cb(invocation, path,
165                                 info->authorize_data);
166
167                 return;
168         } else if (g_strcmp0(method_name, "Authorize") == 0) {
169                 g_dbus_method_invocation_return_value(invocation, NULL);
170         } else if (g_strcmp0(method_name, "Request") == 0) {
171                 char *sender;
172                 bt_obex_agent_info *info;
173                 GDBusProxy *proxy;
174                 char *path = NULL;
175                 char *name = NULL;
176                 GError *err = NULL;
177
178                 info = __find_obex_agent_info((char *)object_path);
179
180                 if (info == NULL)
181                         goto fail;
182
183                 if (conn == NULL)
184                         goto fail;
185
186                 sender = (char *)g_dbus_method_invocation_get_sender(invocation);
187
188                 if (info->name == NULL) {
189                         info->name = sender;
190                 } else {
191                         if (g_strcmp0(sender, info->name) != 0) {
192                                 goto fail;
193                         }
194                 }
195
196                 if (info->request_cb == NULL)
197                         goto fail;
198
199                 g_variant_get(parameters, "(&o&s)", &path, &name);
200                 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_CALL_FLAGS_NONE,
201                                         NULL,
202                                         BT_OBEX_SERVICE_NAME,
203                                         path,
204                                         BT_OBEX_TRANSFER_INTERFACE,
205                                         NULL, &err);
206
207                 if (err) {
208                         BT_ERR("Dbus Err: %s", err->message);
209                         g_clear_error(&err);
210                         goto fail;
211                 }
212
213                 info->request_cb(invocation, proxy, info->request_data);
214                 g_object_unref(proxy);
215                 return;
216
217         } else if (g_strcmp0(method_name, "Progress") == 0) {
218                 BT_DBG("+");
219
220                 bt_obex_agent_info *info;
221                 char *sender;
222                 char *path = NULL;
223                 gint64 transferred;
224                 GDBusProxy *proxy;
225                 GError *err = NULL;
226
227                 info = __find_obex_agent_info((char *)object_path);
228
229                 if (info == NULL)
230                         goto fail;
231
232                 if (conn == NULL)
233                         goto fail;
234
235                 sender = (char *)g_dbus_method_invocation_get_sender(invocation);
236
237                 if (g_strcmp0(sender, info->name) != 0) {
238                         goto fail;
239                 }
240
241                 if (info->progress_cb == NULL)
242                         goto fail;
243
244                 g_variant_get(parameters, "(&ot)", &path, &transferred);
245                 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_CALL_FLAGS_NONE,
246                                         NULL,
247                                         BT_OBEX_SERVICE_NAME,
248                                         path,
249                                         BT_OBEX_TRANSFER_INTERFACE,
250                                         NULL, &err);
251
252                 if (err) {
253                         BT_ERR("Dbus Err: %s", err->message);
254                         g_clear_error(&err);
255                         goto fail;
256                 }
257
258                 info->progress_cb(invocation, proxy, transferred, info->progress_data);
259
260                 g_object_unref(proxy);
261
262                 BT_DBG("-");
263
264                 return;
265         } else if (g_strcmp0(method_name, "Error") == 0) {
266                 bt_obex_agent_info *info;
267                 char *sender;
268                 GDBusProxy *proxy;
269                 char *path, *message;
270                 GError *err = NULL;
271
272                 info = __find_obex_agent_info((char *)object_path);
273
274                 if (info == NULL)
275                         goto fail;
276
277                 if (conn == NULL)
278                         goto fail;
279
280                 sender = (char *)g_dbus_method_invocation_get_sender(invocation);
281
282                 if (g_strcmp0(sender, info->name) != 0) {
283                         goto fail;
284                 }
285
286                 if (info->error_cb == NULL)
287                         goto fail;
288                 g_variant_get(parameters, "(&o&s)", &path, &message);
289                 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_CALL_FLAGS_NONE,
290                                         NULL,
291                                         BT_OBEX_SERVICE_NAME,
292                                         path,
293                                         BT_OBEX_TRANSFER_INTERFACE,
294                                         NULL, &err);
295                 if (err) {
296                         BT_ERR("Dbus Err: %s", err->message);
297                         g_clear_error(&err);
298                         goto fail;
299                 }
300                 info->error_cb(invocation, proxy, message, info->progress_data);
301
302                 g_object_unref(proxy);
303
304                 return;
305         } else if (g_strcmp0(method_name, "Complete") == 0) {
306                 bt_obex_agent_info *info;
307                 char *sender;
308                 GDBusProxy *proxy;
309                 char *path = NULL;
310                 GError *err = NULL;
311
312                 info = __find_obex_agent_info((char *)object_path);
313
314                 if (info == NULL)
315                         goto fail;
316
317                 if (conn == NULL)
318                         goto fail;
319
320                 sender = (char *)g_dbus_method_invocation_get_sender(invocation);
321
322                 if (g_strcmp0(sender, info->name) != 0) {
323                         goto fail;
324                 }
325
326                 if (info->complete_cb == NULL)
327                         goto fail;
328
329                 g_variant_get(parameters, "(&o)", &path);
330                 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_CALL_FLAGS_NONE,
331                                         NULL,
332                                         BT_OBEX_SERVICE_NAME,
333                                         path,
334                                         BT_OBEX_TRANSFER_INTERFACE,
335                                         NULL, &err);
336                 if (err) {
337                         BT_ERR("Dbus Err: %s", err->message);
338                         g_clear_error(&err);
339                         goto fail;
340                 }
341
342                 info->complete_cb(invocation, proxy, info->complete_data);
343
344                 g_object_unref(proxy);
345
346                 return;
347         } else if (g_strcmp0(method_name, "Release") == 0) {
348                 bt_obex_agent_info *info;
349                 char *sender;
350
351                 info = __find_obex_agent_info((char *)object_path);
352
353                 if (info == NULL)
354                         goto fail;
355
356                 sender = (char *)g_dbus_method_invocation_get_sender(invocation);
357
358                 if (info->name) {
359                         /*In H2 if user denies auth,release will come without request and hence
360                         info->name will be NULL */
361                         if (g_strcmp0(sender, info->name) != 0) {
362                                 goto fail;
363                         }
364                 }
365
366                 if (info->release_cb == NULL)
367                         goto fail;
368
369                 info->release_cb(invocation, info->release_data);
370
371                 return;
372         }
373 fail:
374                 BT_ERR("Fail case");
375                 g_dbus_method_invocation_return_value(invocation, NULL);
376 }
377
378 void _bt_obex_agent_new(char *path)
379 {
380         bt_obex_agent_info *info = NULL;
381         GError *error = NULL;
382
383         if (conn == NULL) {
384                 conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
385                 if (error != NULL) {
386                         BT_ERR("Fail to get dbus: %s", error->message);
387                         g_error_free(error);
388                         return;
389                 }
390         }
391         info = (bt_obex_agent_info *)malloc (sizeof(bt_obex_agent_info));
392         if (info) {
393                 memset(info, 0, sizeof(bt_obex_agent_info));
394                 info->path = g_strdup(path);
395                 obex_agent_list = g_slist_append(obex_agent_list, info);
396         }
397 }
398
399 void _bt_obex_agent_destroy(char *path)
400 {
401         bt_obex_agent_info *info = NULL;
402         info = __find_obex_agent_info(path);
403         if (info == NULL) {
404                 BT_ERR("obex agent info not found on path %s", path);
405                 return;
406         }
407         obex_agent_list = g_slist_remove(obex_agent_list, info);
408         if (info->path)
409                 g_free(info->path);
410         if (info->name)
411                 g_free(info->name);
412         if (info->openobex_id)
413                 g_dbus_connection_unregister_object(conn,
414                         info->openobex_id);
415         if (info->obex_agent_id)
416                 g_dbus_connection_unregister_object(conn,
417                         info->obex_agent_id);
418
419         g_free(info);
420 }
421 gboolean _bt_obex_setup(const char *path)
422 {
423         bt_obex_agent_info *info;
424         GDBusProxy *proxy;
425         GDBusNodeInfo *new_conn_node;
426         GError *err = NULL;
427
428         info = __find_obex_agent_info((char *)path);
429
430         retv_if(info == NULL, FALSE);
431
432         proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SESSION,
433                                 G_DBUS_PROXY_FLAGS_NONE,
434                                 NULL,
435                                 BT_OBEX_SERVICE_NAME,
436                                 BT_OBEX_CLIENT_PATH,
437                                 BT_OBEX_AGENT_INTERFACE,
438                                 NULL,
439                                 &err);
440
441         g_free(info->name);
442
443         if (proxy != NULL) {
444                 info->name = g_strdup(g_dbus_proxy_get_name(proxy));
445                 g_object_unref(proxy);
446         } else {
447                 info->name = NULL;
448         }
449
450         new_conn_node = g_dbus_node_info_new_for_xml(obex_service_agent_xml1, NULL);
451         if (new_conn_node == NULL)
452                 return FALSE;
453
454         info->openobex_id = g_dbus_connection_register_object(conn, info->path,
455                                                 new_conn_node->interfaces[0],
456                                                 &method_table,
457                                                 NULL, NULL, &err);
458         g_dbus_node_info_unref(new_conn_node);
459         if (err) {
460                 BT_INFO("Dbus Err: %s", err->message);
461                 g_clear_error(&err);
462                 return FALSE;
463         }
464         if (info->openobex_id == 0)
465                 BT_ERR("Error while registering object");
466         new_conn_node = g_dbus_node_info_new_for_xml(obex_service_agent_xml2, NULL);
467
468         info->obex_agent_id = g_dbus_connection_register_object(conn, info->path,
469                                                 new_conn_node->interfaces[0],
470                                                 &method_table,
471                                                 NULL, NULL, &err);
472         g_dbus_node_info_unref(new_conn_node);
473         if (info->obex_agent_id == 0)
474                 BT_ERR("Error while registering object");
475         if (err) {
476                 BT_INFO("Dbus Err: %s", err->message);
477                 g_clear_error(&err);
478                 return FALSE;
479         }
480         return TRUE;
481 }
482
483 void _bt_obex_set_authorize_cb(char *object_path,
484                          bt_obex_authorize_cb func, gpointer data)
485 {
486         bt_obex_agent_info *info = __find_obex_agent_info(object_path);;
487
488         if (info) {
489                 info->authorize_cb = func;
490                 info->authorize_data = data;
491         }
492 }
493
494 void _bt_obex_set_release_cb(char *object_path,
495                        bt_obex_release_cb func, gpointer data)
496 {
497         bt_obex_agent_info *info = __find_obex_agent_info(object_path);;
498
499         /* Fix : NULL_RETURNS */
500         if (info == NULL)
501                 return;
502
503         info->release_cb = func;
504         info->release_data = data;
505 }
506
507 void _bt_obex_set_request_cb(char *object_path,
508                        bt_obex_request_cb func, gpointer data)
509 {
510         bt_obex_agent_info *info = __find_obex_agent_info(object_path);;
511
512         /* Fix : NULL_RETURNS */
513         if (info == NULL)
514                 return;
515
516         info->request_cb = func;
517         info->request_data = data;
518 }
519
520 void _bt_obex_set_progress_cb(char *object_path,
521                         bt_obex_progress_cb func, gpointer data)
522 {
523         bt_obex_agent_info *info = __find_obex_agent_info(object_path);;
524
525         /* Fix : NULL_RETURNS */
526         if (info == NULL)
527                 return;
528
529         info->progress_cb = func;
530         info->progress_data = data;
531 }
532
533 void _bt_obex_set_complete_cb(char *object_path,
534                         bt_obex_complete_cb func, gpointer data)
535 {
536         bt_obex_agent_info *info =__find_obex_agent_info(object_path);;
537
538         /* Fix : NULL_RETURNS */
539         if (info == NULL)
540                 return;
541
542         info->complete_cb = func;
543         info->complete_data = data;
544 }
545
546 void _bt_obex_set_error_cb(char *object_path,
547                         bt_obex_error_cb func, gpointer data)
548 {
549         bt_obex_agent_info *info = __find_obex_agent_info(object_path);;
550
551         /* Fix : NULL_RETURNS */
552         if (info == NULL)
553                 return;
554
555         info->error_cb = func;
556         info->error_data = data;
557 }