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