Remove wrong dependency in the systemd service file
[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
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                 char *sender;
177                 bt_obex_agent_info *info;
178                 GDBusProxy *proxy;
179                 char *path = NULL;
180                 char *name = NULL;
181                 GError *err = NULL;
182
183                 info = __find_obex_agent_info((char *)object_path);
184
185                 if (info == NULL)
186                         goto fail;
187
188                 if (conn == NULL)
189                         goto fail;
190
191                 sender = (char *)g_dbus_method_invocation_get_sender(invocation);
192
193                 if (info->name == NULL) {
194                         info->name = sender;
195                 } else {
196                         if (g_strcmp0(sender, info->name) != 0)
197                                 goto fail;
198                 }
199
200                 if (info->request_cb == NULL)
201                         goto fail;
202
203                 g_variant_get(parameters, "(&o&s)", &path, &name);
204                 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_CALL_FLAGS_NONE,
205                                         NULL,
206                                         BT_OBEX_SERVICE_NAME,
207                                         path,
208                                         BT_OBEX_TRANSFER_INTERFACE,
209                                         NULL, &err);
210
211                 if (err) {
212                         BT_ERR("Dbus Err: %s", err->message);
213                         g_clear_error(&err);
214                         goto fail;
215                 }
216
217                 info->request_cb(invocation, proxy, info->request_data);
218                 g_object_unref(proxy);
219                 return;
220
221         } else if (g_strcmp0(method_name, "Progress") == 0) {
222                 BT_DBG("+");
223
224                 bt_obex_agent_info *info;
225                 char *sender;
226                 char *path = NULL;
227                 gint64 transferred;
228                 GDBusProxy *proxy;
229                 GError *err = NULL;
230
231                 info = __find_obex_agent_info((char *)object_path);
232
233                 if (info == NULL)
234                         goto fail;
235
236                 if (conn == NULL)
237                         goto fail;
238
239                 sender = (char *)g_dbus_method_invocation_get_sender(invocation);
240
241                 if (g_strcmp0(sender, info->name) != 0)
242                         goto fail;
243
244                 if (info->progress_cb == NULL)
245                         goto fail;
246
247                 g_variant_get(parameters, "(&ot)", &path, &transferred);
248                 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_CALL_FLAGS_NONE,
249                                         NULL,
250                                         BT_OBEX_SERVICE_NAME,
251                                         path,
252                                         BT_OBEX_TRANSFER_INTERFACE,
253                                         NULL, &err);
254
255                 if (err) {
256                         BT_ERR("Dbus Err: %s", err->message);
257                         g_clear_error(&err);
258                         goto fail;
259                 }
260
261                 info->progress_cb(invocation, proxy, transferred, info->progress_data);
262
263                 g_object_unref(proxy);
264
265                 BT_DBG("-");
266
267                 return;
268         } else if (g_strcmp0(method_name, "Error") == 0) {
269                 bt_obex_agent_info *info;
270                 char *sender;
271                 GDBusProxy *proxy;
272                 char *path, *message;
273                 GError *err = NULL;
274
275                 info = __find_obex_agent_info((char *)object_path);
276
277                 if (info == NULL)
278                         goto fail;
279
280                 if (conn == NULL)
281                         goto fail;
282
283                 sender = (char *)g_dbus_method_invocation_get_sender(invocation);
284
285                 if (g_strcmp0(sender, info->name) != 0)
286                         goto fail;
287
288                 if (info->error_cb == NULL)
289                         goto fail;
290                 g_variant_get(parameters, "(&o&s)", &path, &message);
291                 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_CALL_FLAGS_NONE,
292                                         NULL,
293                                         BT_OBEX_SERVICE_NAME,
294                                         path,
295                                         BT_OBEX_TRANSFER_INTERFACE,
296                                         NULL, &err);
297                 if (err) {
298                         BT_ERR("Dbus Err: %s", err->message);
299                         g_clear_error(&err);
300                         goto fail;
301                 }
302                 info->error_cb(invocation, proxy, message, info->progress_data);
303
304                 g_object_unref(proxy);
305
306                 return;
307         } else if (g_strcmp0(method_name, "Complete") == 0) {
308                 bt_obex_agent_info *info;
309                 char *sender;
310                 GDBusProxy *proxy;
311                 char *path = NULL;
312                 GError *err = NULL;
313
314                 info = __find_obex_agent_info((char *)object_path);
315
316                 if (info == NULL)
317                         goto fail;
318
319                 if (conn == NULL)
320                         goto fail;
321
322                 sender = (char *)g_dbus_method_invocation_get_sender(invocation);
323
324                 if (g_strcmp0(sender, info->name) != 0)
325                         goto fail;
326
327                 if (info->complete_cb == NULL)
328                         goto fail;
329
330                 g_variant_get(parameters, "(&o)", &path);
331                 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_CALL_FLAGS_NONE,
332                                         NULL,
333                                         BT_OBEX_SERVICE_NAME,
334                                         path,
335                                         BT_OBEX_TRANSFER_INTERFACE,
336                                         NULL, &err);
337                 if (err) {
338                         BT_ERR("Dbus Err: %s", err->message);
339                         g_clear_error(&err);
340                         goto fail;
341                 }
342
343                 info->complete_cb(invocation, proxy, info->complete_data);
344
345                 g_object_unref(proxy);
346
347                 return;
348         } else if (g_strcmp0(method_name, "Release") == 0) {
349                 bt_obex_agent_info *info;
350                 char *sender;
351
352                 info = __find_obex_agent_info((char *)object_path);
353
354                 if (info == NULL)
355                         goto fail;
356
357                 sender = (char *)g_dbus_method_invocation_get_sender(invocation);
358
359                 if (info->name) {
360                         /*In H2 if user denies auth,release will come without request and hence
361                         info->name will be NULL */
362                         if (g_strcmp0(sender, info->name) != 0)
363                                 goto fail;
364                 }
365
366                 if (info->release_cb == NULL)
367                         goto fail;
368
369                 info->release_cb(invocation, info->release_data);
370
371                 return;
372         } else if (g_strcmp0(method_name, "ReplyAuthorize") == 0) {
373                 const guint accept;
374
375                 g_variant_get(parameters, "(u)", &accept);
376                 BT_DBG("Accept: %d", accept);
377
378                 if (accept == 0) {
379                         BT_DBG("Transfer accepted");
380                         _bt_obex_server_reply_accept();
381                 } else {
382                         BT_ERR("Transfer denied");
383                         _bt_obex_server_reject_authorize();
384                 }
385         }
386 fail:
387                 BT_ERR("Fail case");
388                 g_dbus_method_invocation_return_value(invocation, NULL);
389 }
390
391 void _bt_obex_agent_new(char *path)
392 {
393         bt_obex_agent_info *info = NULL;
394         GError *error = NULL;
395
396         if (conn == NULL) {
397                 conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
398                 if (error != NULL) {
399                         BT_ERR("Fail to get dbus: %s", error->message);
400                         g_error_free(error);
401                         return;
402                 }
403                 auth_reply_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, 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         }
410         info = (bt_obex_agent_info *)malloc(sizeof(bt_obex_agent_info));
411         if (info) {
412                 memset(info, 0, sizeof(bt_obex_agent_info));
413                 info->path = g_strdup(path);
414                 obex_agent_list = g_slist_append(obex_agent_list, info);
415         }
416 }
417
418 void _bt_obex_agent_destroy(char *path)
419 {
420         bt_obex_agent_info *info = NULL;
421         info = __find_obex_agent_info(path);
422         if (info == NULL) {
423                 BT_ERR("obex agent info not found on path %s", path);
424                 return;
425         }
426         obex_agent_list = g_slist_remove(obex_agent_list, info);
427         if (info->path)
428                 g_free(info->path);
429         if (info->name)
430                 g_free(info->name);
431         if (info->openobex_id)
432                 g_dbus_connection_unregister_object(conn,
433                         info->openobex_id);
434         if (info->obex_agent_id)
435                 g_dbus_connection_unregister_object(conn,
436                         info->obex_agent_id);
437         if (info->obex_reply_id)
438                 g_dbus_connection_unregister_object(auth_reply_conn,
439                                         info->obex_reply_id);
440
441         g_free(info);
442 }
443 gboolean _bt_obex_setup(const char *path)
444 {
445         bt_obex_agent_info *info;
446         GDBusProxy *proxy;
447         GDBusNodeInfo *new_conn_node = NULL;
448         GDBusNodeInfo *auth_reply_node = NULL;
449         GError *err = NULL;
450
451         info = __find_obex_agent_info((char *)path);
452
453         retv_if(info == NULL, FALSE);
454
455         proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SESSION,
456                                 G_DBUS_PROXY_FLAGS_NONE,
457                                 NULL,
458                                 BT_OBEX_SERVICE_NAME,
459                                 BT_OBEX_CLIENT_PATH,
460                                 BT_OBEX_AGENT_INTERFACE,
461                                 NULL,
462                                 &err);
463
464         g_free(info->name);
465
466         if (proxy != NULL) {
467                 info->name = g_strdup(g_dbus_proxy_get_name(proxy));
468                 g_object_unref(proxy);
469         } else {
470                 info->name = NULL;
471         }
472
473         new_conn_node = g_dbus_node_info_new_for_xml(obex_service_agent_xml1, NULL);
474         if (new_conn_node == NULL)
475                 return FALSE;
476
477         info->openobex_id = g_dbus_connection_register_object(conn, info->path,
478                                                 new_conn_node->interfaces[0],
479                                                 &method_table,
480                                                 NULL, NULL, &err);
481         g_dbus_node_info_unref(new_conn_node);
482         if (err) {
483                 BT_ERR("Dbus Err: %s", err->message);
484                 g_clear_error(&err);
485                 return FALSE;
486         }
487         if (info->openobex_id == 0)
488                 BT_ERR("Error while registering object");
489
490         new_conn_node = g_dbus_node_info_new_for_xml(obex_service_agent_xml2, NULL);
491         if (new_conn_node == NULL)
492                 return FALSE;
493
494         info->obex_agent_id = g_dbus_connection_register_object(conn, info->path,
495                                                 new_conn_node->interfaces[0],
496                                                 &method_table,
497                                                 NULL, NULL, &err);
498         g_dbus_node_info_unref(new_conn_node);
499         if (info->obex_agent_id == 0)
500                 BT_ERR("Error while registering object");
501         if (err) {
502                 BT_ERR("Dbus Err: %s", err->message);
503                 g_clear_error(&err);
504                 return FALSE;
505         }
506
507         auth_reply_node = g_dbus_node_info_new_for_xml(obex_service_reply_xml3, NULL);
508
509         if (auth_reply_node == NULL) {
510                 BT_ERR("Fail to create the node info for xml");
511                 return FALSE;
512         }
513
514         info->obex_reply_id = g_dbus_connection_register_object(auth_reply_conn, info->path,
515                 auth_reply_node->interfaces[0], &method_table, NULL, NULL, &err);
516         g_dbus_node_info_unref(auth_reply_node);
517         if (info->obex_reply_id == 0)
518                 BT_ERR("Error while registering object");
519         if (err) {
520                 BT_ERR("Dbus Err: %s", err->message);
521                 g_clear_error(&err);
522                 return FALSE;
523         }
524         return TRUE;
525 }
526
527 void _bt_obex_set_authorize_cb(char *object_path,
528                          bt_obex_authorize_cb func, gpointer data)
529 {
530         bt_obex_agent_info *info = __find_obex_agent_info(object_path);;
531         if (info == NULL)
532                 return;
533
534         info->authorize_cb = func;
535         info->authorize_data = data;
536 }
537
538 void _bt_obex_set_release_cb(char *object_path,
539                        bt_obex_release_cb func, gpointer data)
540 {
541         bt_obex_agent_info *info = __find_obex_agent_info(object_path);;
542         if (info == NULL)
543                 return;
544
545         info->release_cb = func;
546         info->release_data = data;
547 }
548
549 void _bt_obex_set_request_cb(char *object_path,
550                        bt_obex_request_cb func, gpointer data)
551 {
552         bt_obex_agent_info *info = __find_obex_agent_info(object_path);;
553         if (info == NULL)
554                 return;
555
556         info->request_cb = func;
557         info->request_data = data;
558 }
559
560 void _bt_obex_set_progress_cb(char *object_path,
561                         bt_obex_progress_cb func, gpointer data)
562 {
563         bt_obex_agent_info *info = __find_obex_agent_info(object_path);;
564         if (info == NULL)
565                 return;
566
567         info->progress_cb = func;
568         info->progress_data = data;
569 }
570
571 void _bt_obex_set_complete_cb(char *object_path,
572                         bt_obex_complete_cb func, gpointer data)
573 {
574         bt_obex_agent_info *info = __find_obex_agent_info(object_path);;
575         if (info == NULL)
576                 return;
577
578         info->complete_cb = func;
579         info->complete_data = data;
580 }
581
582 void _bt_obex_set_error_cb(char *object_path,
583                         bt_obex_error_cb func, gpointer data)
584 {
585         bt_obex_agent_info *info = __find_obex_agent_info(object_path);;
586         if (info == NULL)
587                 return;
588
589         info->error_cb = func;
590         info->error_data = data;
591 }