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