Add the info dbus message of transfer cancel
[platform/core/connectivity/bluetooth-frwk.git] / lib / obex.c
1 /*
2 * Bluetooth-Frwk-NG
3 *
4 * Copyright (c) 2013-2014 Intel Corporation.
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 <stdlib.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <gio/gio.h>
24 #include "common.h"
25 #include "obex.h"
26
27 #define OBEX_NAME "org.bluez.obex"
28
29 #define OBJECT_MANAGE_PATH "/"
30
31 #define OBJECT_OBEX_PATH "/org/bluez/obex"
32
33 #define OBEX_AGENT_INTERFACE "org.bluez.obex.AgentManager1"
34
35 #define PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
36
37 #define MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager"
38
39 #define OBEX_SESSION_INTERFACE "org.bluez.obex.Session1"
40
41 #define OBEX_TRANSFER_INTERFACE "org.bluez.obex.Transfer1"
42
43 static GDBusConnection *g_connection;
44 static int g_opp_startup;
45 static GDBusProxy *manager_proxy;
46 static GDBusObjectManager *object_manager;
47
48 static obex_agent_added_cb_t obex_agent_added_cb;
49 static void *obex_agent_added_cb_data;
50 static GList *transfer_watched_list;
51
52 static GDBusConnection *_obex_get_session_dbus(void)
53 {
54         GError *error = NULL;
55
56         if (g_connection)
57                 return g_connection;
58
59         g_connection =
60                 g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
61         if (g_connection == NULL) {
62                 DBG("%s", error->message);
63                 g_error_free(error);
64         }
65
66         return g_connection;
67 }
68
69 void obex_agent_set_agent_added(obex_agent_added_cb_t cb, void *user_data)
70 {
71         obex_agent_added_cb = cb;
72         obex_agent_added_cb_data = user_data;
73 }
74
75 void obex_agent_unset_agent_added(void)
76 {
77         obex_agent_added_cb = NULL;
78         obex_agent_added_cb_data = NULL;
79 }
80
81 struct agent_data {
82         agent_cb_t cb;
83         void *user_data;
84         GDBusConnection *conn;
85 };
86
87 static void agent_callback(GObject *source_object,
88                                         GAsyncResult *res,
89                                         gpointer user_data)
90 {
91         GVariant *ret;
92         GError *error = NULL;
93         enum bluez_error_type error_type = ERROR_NONE;
94         struct agent_data *agent_data = user_data;
95
96         DBG("+");
97
98         ret = g_dbus_connection_call_finish(agent_data->conn,
99                                                 res, &error);
100         if (ret == NULL) {
101                 error_type = get_error_type(error);
102                 ERROR("error = %d", error_type);
103                 g_free(error);
104         }
105
106         agent_data->cb(error_type, agent_data->user_data);
107
108         g_free(agent_data);
109
110         DBG("-");
111 }
112
113 void obex_agent_register_agent(const char *agent_path,
114                                 agent_cb_t cb,
115                                 void *user_data)
116 {
117         struct agent_data *register_data;
118         GDBusConnection *connection = _obex_get_session_dbus();
119
120         DBG("");
121
122         register_data = g_new0(struct agent_data, 1);
123         if (register_data == NULL) {
124                 ERROR("no memory");
125                 return;
126         }
127
128         register_data->cb = cb;
129         register_data->user_data = user_data;
130         register_data->conn = connection;
131
132         if (g_opp_startup)
133                 g_dbus_connection_call(connection, "org.bluez.obex",
134                                         "/org/bluez/obex",
135                                         "org.bluez.obex.AgentManager1",
136                                         "RegisterAgent",
137                                         g_variant_new("(o)", agent_path),
138                                         NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL,
139                                         agent_callback, register_data);
140         else
141                 ERROR("agent not registered");
142 }
143
144 void obex_agent_unregister_agent(const char *agent_path,
145                                         agent_cb_t cb,
146                                         void *user_data)
147 {
148         struct agent_data *unregister_data;
149         GDBusConnection *connection = _obex_get_session_dbus();
150
151         DBG("");
152
153         unregister_data = g_new0(struct agent_data, 1);
154         if (unregister_data == NULL) {
155                 ERROR("no memory");
156                 return;
157         }
158
159         unregister_data->cb = cb;
160         unregister_data->user_data = user_data;
161
162         if (g_opp_startup)
163                 g_dbus_connection_call(connection, "org.bluez.obex",
164                                         "/org/bluez/obex",
165                                         "org.bluez.obex.AgentManager1",
166                                         "UnregisterAgent",
167                                         g_variant_new("(o)", agent_path),
168                                         NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL,
169                                         agent_callback, unregister_data);
170         else
171                 ERROR("agent not registered");
172 }
173
174 static enum transfer_state get_transfer_state_from_string(const char *string)
175 {
176         if (string == NULL)
177                 return OBEX_TRANSFER_UNKNOWN;
178
179         if (!g_strcmp0(string, "queued"))
180                 return OBEX_TRANSFER_QUEUED;
181
182         if (!g_strcmp0(string, "active"))
183                 return OBEX_TRANSFER_ACTIVE;
184
185         if (!g_strcmp0(string, "complete"))
186                 return OBEX_TRANSFER_COMPLETE;
187
188         if (!g_strcmp0(string, "error"))
189                 return OBEX_TRANSFER_ERROR;
190
191         return OBEX_TRANSFER_UNKNOWN;
192 }
193
194 enum transfer_state obex_transfer_get_property_state(const char *path)
195 {
196         GDBusProxy *p_proxy;
197         char *status = NULL;
198
199         DBG("");
200
201         p_proxy = g_dbus_proxy_new_for_bus_sync(
202                                         G_BUS_TYPE_SESSION, 0,
203                                         NULL,
204                                         "org.bluez.obex",
205                                         path,
206                                         PROPERTIES_INTERFACE,
207                                         NULL, NULL);
208
209         if (p_proxy)
210                 status = property_get_string(p_proxy,
211                                 OBEX_TRANSFER_INTERFACE, "Status");
212
213         g_object_unref(p_proxy);
214
215         return get_transfer_state_from_string(status);
216 }
217
218 int obex_transfer_get_property_transferred(const char *path,
219                                 guint64 *u64)
220 {
221         GDBusProxy *p_proxy;
222         int ret = -1;
223
224         DBG("");
225
226         p_proxy = g_dbus_proxy_new_for_bus_sync(
227                                         G_BUS_TYPE_SESSION, 0,
228                                         NULL,
229                                         "org.bluez.obex",
230                                         path,
231                                         PROPERTIES_INTERFACE,
232                                         NULL, NULL);
233
234         if (p_proxy)
235                 ret = property_get_uint64(p_proxy,
236                         OBEX_TRANSFER_INTERFACE, "Transferred", u64);
237
238         g_object_unref(p_proxy);
239
240         return ret;
241 }
242
243 int obex_transfer_get_property_size(const char *path,
244                                 guint64 *u64)
245 {
246         GDBusProxy *p_proxy;
247         int ret = -1;
248
249         DBG("path = %s", path);
250         p_proxy = g_dbus_proxy_new_for_bus_sync(
251                                         G_BUS_TYPE_SESSION, 0,
252                                         NULL,
253                                         "org.bluez.obex",
254                                         path,
255                                         PROPERTIES_INTERFACE,
256                                         NULL, NULL);
257
258         if (p_proxy)
259                 ret = property_get_uint64(p_proxy,
260                         OBEX_TRANSFER_INTERFACE, "Size", u64);
261
262         g_object_unref(p_proxy);
263
264         return ret;
265 }
266
267 static void parse_object(gpointer data, gpointer user_data)
268 {
269         GDBusObject *obj = data;
270         const char *path = g_dbus_object_get_object_path(obj);
271
272
273         DBG("object path name %s", path);
274
275         if (!g_strcmp0(path, OBJECT_OBEX_PATH)) {
276                 if (g_opp_startup == 1)
277                         return;
278                 g_opp_startup = 1;
279                 if (obex_agent_added_cb)
280                         obex_agent_added_cb(obex_agent_added_cb_data);
281         }
282
283         return;
284 }
285
286
287 static void interfaces_removed(GVariant *parameters)
288 {
289         gchar *object_path;
290         GVariantIter *iter;
291
292         gchar *parameters_s = g_variant_print(parameters, TRUE);
293
294         g_variant_get(parameters, "(oas)", &object_path, &iter);
295
296         DBG("%s", parameters_s);
297
298         g_free(parameters_s);
299
300         DBG("%s", object_path);
301
302         if (!g_strcmp0(object_path, OBJECT_OBEX_PATH))
303                 g_opp_startup = 0;
304 }
305
306 static void interfaces_added(GVariant *parameters)
307 {
308         gchar *object_path;
309         GDBusObject *obj;
310
311         g_variant_get(parameters, "(oa{sa{sv}})", &object_path, NULL);
312
313         DBG("object %s", object_path);
314
315         obj = g_dbus_object_manager_get_object(object_manager, object_path);
316
317         if (obj)
318                 parse_object(obj, NULL);
319 }
320
321 static gboolean handle_interfaces_added(gpointer user_data)
322 {
323         GVariant *parameters = user_data;
324
325         interfaces_added(parameters);
326
327         g_variant_unref(parameters);
328
329         return FALSE;
330 }
331
332 static void interfaces_changed(GDBusProxy *proxy,
333                                 gchar *sender_name,
334                                 gchar *signal_name,
335                                 GVariant *parameters,
336                                 gpointer user_data)
337 {
338         if (!g_strcmp0(signal_name, "InterfacesAdded"))
339                 g_idle_add(handle_interfaces_added,
340                                 g_variant_ref_sink(parameters));
341         if (!g_strcmp0(signal_name, "InterfacesRemoved"))
342                 interfaces_removed(parameters);
343 }
344
345 int obex_agent_get_agent(void)
346 {
347         return g_opp_startup;
348 }
349
350 int obex_lib_init(void)
351 {
352         GList *obj_list;
353
354         DBG("");
355
356         if (object_manager != NULL)
357                 return 0;
358
359         manager_proxy = g_dbus_proxy_new_for_bus_sync(
360                                                 G_BUS_TYPE_SESSION, 0,
361                                                 NULL,
362                                                 OBEX_NAME,
363                                                 "/",
364                                                 MANAGER_INTERFACE,
365                                                 NULL, NULL);
366
367         if (manager_proxy == NULL)
368                 ERROR("create manager_proxy error");
369         else {
370                 DBG("manager proxy 0x%p created", manager_proxy);
371
372                 g_signal_connect(manager_proxy,
373                                 "g-signal",
374                                 G_CALLBACK(interfaces_changed),
375                                 NULL);
376         }
377
378         object_manager = g_dbus_object_manager_client_new_for_bus_sync(
379                                                         G_BUS_TYPE_SESSION,
380                                                         0,
381                                                         OBEX_NAME,
382                                                         OBJECT_MANAGE_PATH,
383                                                         NULL, NULL, NULL,
384                                                         NULL, NULL);
385
386         if (object_manager == NULL) {
387                 ERROR("create object manager error");
388                 /* TODO: define error type */
389                 return -1;
390         }
391
392         DBG("object manager %p is created", object_manager);
393
394         obj_list = g_dbus_object_manager_get_objects(object_manager);
395
396         g_list_foreach(obj_list, parse_object, NULL);
397
398         return 0;
399 }
400
401 static void destruct_obex_object_manager(void)
402 {
403         DBG("");
404
405         g_object_unref(object_manager);
406
407         object_manager = NULL;
408 }
409
410 void obex_lib_deinit(void)
411 {
412         DBG("");
413
414         if (manager_proxy)
415                 g_object_unref(manager_proxy);
416
417         destruct_obex_object_manager();
418 }
419
420 struct obex_session_result {
421         obex_session_state_cb cb;
422         void *user_data;
423         GDBusConnection *conn;
424 };
425
426 static const char *get_obex_target_string(enum obex_target target)
427 {
428         switch (target) {
429         case OBEX_TARGET_UNKNOWN:
430                 return NULL;
431         case OBEX_FTP:
432                 return "ftp";
433         case OBEX_MAP:
434                 return "map";
435         case OBEX_OPP:
436                 return "opp";
437         case OBEX_PBAP:
438                 return "pbap";
439         case OBEX_SYNC:
440                 return "sync";
441         default:
442                 return NULL;
443         }
444
445         return NULL;
446 }
447
448 static void create_session_cb(GObject *object,
449                                 GAsyncResult *res,
450                                 gpointer user_data)
451 {
452         GError *error;
453         char *session;
454         GVariant *result;
455         struct obex_session_result *async_node;
456
457         error = NULL;
458         async_node = user_data;
459
460         DBG("+");
461
462         result = g_dbus_connection_call_finish(async_node->conn,
463                                                 res, &error);
464
465         if (error) {
466                 ERROR("create session error %s", error->message);
467
468                 async_node->cb(NULL, NULL, OBEX_SESSION_FAILED,
469                                         async_node->user_data,
470                                         g_strdup(error->message));
471
472                 g_error_free(error);
473         } else {
474
475                 g_variant_get(result, "(o)", &session);
476
477                 DBG("Sesseion created %s", session);
478
479                 async_node->cb(NULL, session, OBEX_SESSION_CREATED,
480                                         async_node->user_data, NULL);
481
482                 g_free(session);
483
484                 g_variant_unref(result);
485         }
486
487         g_free(async_node);
488
489         DBG("-");
490 }
491
492 static void remove_session_cb(GObject *object,
493                                 GAsyncResult *res,
494                                 gpointer user_data)
495 {
496         GError *error;
497         GVariant *result;
498         GDBusConnection *conn = user_data;
499
500         DBG("");
501
502         error = NULL;
503         result = g_dbus_connection_call_finish(conn, res, &error);
504
505         if (error) {
506                 ERROR("create session error %s", error->message);
507
508                 g_error_free(error);
509         } else
510                 g_variant_unref(result);
511 }
512
513 int obex_create_session(const char *destination,
514                                 enum obex_target target,
515                                 obex_session_state_cb cb,
516                                 void *data)
517 {
518         GVariantBuilder *builder;
519         const char *target_s;
520         GVariant *target_v;
521         struct obex_session_result *async_node;
522         GDBusConnection *connection = _obex_get_session_dbus();
523
524         DBG("+");
525
526         if (!connection)
527                 return -1;
528
529         async_node = g_new0(struct obex_session_result, 1);
530         if (async_node == NULL) {
531                 ERROR("no memory");
532                 return -1;
533         }
534
535         async_node->cb = cb;
536         async_node->user_data = data;
537         async_node->conn = connection;
538
539         target_s = get_obex_target_string(target);
540         target_v = g_variant_new("s", target_s);
541         builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
542         g_variant_builder_add(builder, "{sv}", "Target", target_v);
543
544         DBG("destination = %s, target_s = %s", destination, target_s);
545
546         g_dbus_connection_call(connection, "org.bluez.obex",
547                                         "/org/bluez/obex",
548                                         "org.bluez.obex.Client1",
549                                         "CreateSession",
550                                         g_variant_new("(sa{sv})",
551                                         destination, builder),
552                                         NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL,
553                                         create_session_cb, async_node);
554
555         g_variant_builder_unref(builder);
556
557         DBG("-");
558
559         return 0;
560 }
561
562 void obex_session_remove_session(const char *object_path)
563 {
564         GDBusConnection *connection = _obex_get_session_dbus();
565
566         DBG("");
567
568         if (!connection)
569                 return;
570
571         g_dbus_connection_call(connection, "org.bluez.obex",
572                                 "/org/bluez/obex",
573                                 "org.bluez.obex.Client1",
574                                 "RemoveSession",
575                                 g_variant_new("(o)", object_path),
576                                 NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL,
577                                 remove_session_cb, connection);
578 }
579
580 struct obex_transfer_result {
581         obex_transfer_state_cb cb;
582         void *user_data;
583         GDBusConnection *conn;
584 };
585
586 static void create_transfer_cb(GObject *object,
587                                 GAsyncResult *res,
588                                 gpointer user_data)
589 {
590         GError *error = NULL;
591         char *transfer;
592         GVariant *result;
593         struct obex_transfer_result *async_node = user_data;
594
595         DBG("+");
596
597         result = g_dbus_connection_call_finish(async_node->conn,
598                                                 res, &error);
599
600         async_node = user_data;
601
602         if (error) {
603                 ERROR("transfer error %s", error->message);
604
605                 async_node->cb(NULL, OBEX_TRANSFER_ERROR, NULL, 0, 0,
606                                 NULL, g_strdup(error->message));
607
608                 g_error_free(error);
609         } else {
610                 g_variant_get(result, "(oa{sv})", &transfer, NULL);
611
612                 DBG("transfer created %s", transfer);
613
614                 async_node->cb(g_strdup(transfer), OBEX_TRANSFER_QUEUED,
615                                 NULL, 0, 0, async_node->user_data, NULL);
616
617                 g_free(transfer);
618
619                 g_variant_unref(result);
620         }
621
622         g_free(async_node);
623
624         DBG("-");
625 }
626
627 void obex_session_opp_send_file(const char *session,
628                                 const char *file,
629                                 obex_transfer_state_cb cb,
630                                 void *data)
631 {
632         struct obex_transfer_result *async_node;
633         GDBusConnection *connection = _obex_get_session_dbus();
634
635         DBG("");
636
637         if (!connection)
638                 return;
639
640         async_node = g_new0(struct obex_transfer_result, 1);
641         if (async_node == NULL) {
642                 ERROR("no memory");
643                 return;
644         }
645
646         async_node->cb = cb;
647         async_node->user_data = data;
648         async_node->conn = connection;
649
650         g_dbus_connection_call(connection, "org.bluez.obex",
651                                         session,
652                                         "org.bluez.obex.ObjectPush1",
653                                         "SendFile",
654                                         g_variant_new("(s)", file),
655                                         NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL,
656                                         create_transfer_cb, async_node);
657 }
658
659 struct obex_watch_result {
660         obex_transfer_state_cb cb;
661         void *user_data;
662         char *path;
663         unsigned int proxy_id;
664         GDBusProxy *proxy;
665 };
666
667 int obex_get_transfer_id(const char *transfer_path, enum obex_role role)
668 {
669         int id;
670         char *p = g_strrstr(transfer_path, "transfer");
671
672         if (p == NULL) {
673                 ERROR("Can't get transfer id");
674                 return -1;
675         }
676
677         id = atoi(8 + p);
678
679         if (role == OBEX_SERVER)
680                 id = id + 10000;
681
682         DBG("transfer id %d", id);
683
684         return id;
685 }
686
687 static struct obex_watch_result *find_watch_node(const char *path)
688 {
689         struct obex_watch_result *node;
690         GList *list, *next;
691
692         DBG("path = %s", path);
693
694         if (!transfer_watched_list ||
695                         !g_list_length(transfer_watched_list))
696                 return NULL;
697
698         for (list = g_list_first(transfer_watched_list);
699                                         list; list = next) {
700                 next = g_list_next(list);
701                 node = list->data;
702
703                 if (node && !g_strcmp0(node->path, path))
704                         return node;
705         }
706
707         return NULL;
708 }
709
710 static void transfer_properties_changed(GDBusProxy *proxy,
711                                         GVariant *changed_properties,
712                                         GStrv *invalidated_properties,
713                                         gpointer user_data)
714 {
715         struct obex_watch_result *async_node = user_data;
716         gchar *status;
717         enum transfer_state state;
718         gchar *name = NULL;
719         guint64 size = 0;
720         gboolean variant_found;
721         guint64 transferred = 0;
722         GDBusProxy *p_proxy;
723
724         gchar *properties = g_variant_print(changed_properties, TRUE);
725
726         DBG("properties %s", properties);
727         g_free(properties);
728
729         if (!async_node || !async_node->path)
730                 return;
731
732         p_proxy = g_dbus_proxy_new_for_bus_sync(
733                                         G_BUS_TYPE_SESSION, 0,
734                                         NULL,
735                                         "org.bluez.obex",
736                                         async_node->path,
737                                         PROPERTIES_INTERFACE,
738                                         NULL, NULL);
739
740         if (!p_proxy)
741                 return;
742
743         variant_found = g_variant_lookup(changed_properties,
744                                         "Status", "s", &status);
745
746         if (variant_found) {
747                 DBG("status = %s", status);
748                 state = get_transfer_state_from_string(status);
749                 if (state == OBEX_TRANSFER_ERROR ||
750                         state == OBEX_TRANSFER_COMPLETE)
751                         goto done;
752         } else {
753                 status = property_get_string(p_proxy,
754                         OBEX_TRANSFER_INTERFACE, "Status");
755                 state = get_transfer_state_from_string(status);
756         }
757
758         variant_found = g_variant_lookup(changed_properties,
759                                 "Transferred", "t", &transferred);
760
761         if (!variant_found)
762                 property_get_uint64(p_proxy,
763                         OBEX_TRANSFER_INTERFACE,
764                         "Transferred", &transferred);
765         name = property_get_string(p_proxy,
766                         OBEX_TRANSFER_INTERFACE, "Filename");
767
768         property_get_uint64(p_proxy,
769                         OBEX_TRANSFER_INTERFACE, "Size", &size);
770
771         DBG("state: %d, %ju, %s, %s, %ju", state, transferred,
772                                                 name, status, size);
773
774         async_node->cb(async_node->path, state, name, size,
775                         transferred, async_node->user_data, NULL);
776
777         g_object_unref(p_proxy);
778         return;
779 done:
780         DBG("state: %d, %ju, %s, %s, %ju", state, transferred,
781                                                 name, status, size);
782
783         async_node->cb(async_node->path, state, name, size, transferred,
784                                 async_node->user_data, NULL);
785
786         g_signal_handler_disconnect(async_node->proxy,
787                                                 async_node->proxy_id);
788
789         transfer_watched_list = g_list_remove(transfer_watched_list,
790                                                         async_node);
791         g_object_unref(p_proxy);
792         g_object_unref(async_node->proxy);
793         if (async_node->path)
794                 g_free(async_node->path);
795         async_node->path = NULL;
796         g_free(async_node);
797         async_node = NULL;
798 }
799
800 /* notify specific transfer */
801 int obex_transfer_set_notify(char *transfer_path,
802                                 obex_transfer_state_cb cb, void *data)
803 {
804         struct obex_watch_result *async_node;
805         GDBusProxy *proxy;
806
807         DBG("");
808
809         async_node = g_new0(struct obex_watch_result, 1);
810         if (async_node == NULL) {
811                 ERROR("no memory");
812                 return -1;
813         }
814
815         DBG("transfer_path = %s", transfer_path);
816         proxy = g_dbus_proxy_new_for_bus_sync(
817                                         G_BUS_TYPE_SESSION, 0,
818                                         NULL,
819                                         "org.bluez.obex",
820                                         transfer_path,
821                                         "org.bluez.obex.Transfer1",
822                                         NULL, NULL);
823
824         if (proxy == NULL) {
825                 g_free(async_node);
826                 WARN("properties proxy error");
827                 return -1;
828         }
829
830         async_node->cb = cb;
831         async_node->user_data = data;
832         async_node->proxy = g_object_ref(proxy);
833         async_node->path = g_strdup(transfer_path);
834
835         async_node->proxy_id = g_signal_connect(async_node->proxy,
836                         "g-properties-changed",
837                         G_CALLBACK(transfer_properties_changed),
838                         async_node);
839
840         transfer_watched_list = g_list_append(transfer_watched_list,
841                                                         async_node);
842
843         return 0;
844 }
845
846 void obex_transfer_clear_notify(char *transfer_path)
847 {
848         struct obex_watch_result *async_node;
849
850         DBG("transfer_path = %s", transfer_path);
851
852         if (!transfer_path)
853                 return;
854
855         async_node = find_watch_node(transfer_path);
856         if (!async_node)
857                 return;
858
859         g_signal_handler_disconnect(async_node->proxy,
860                                         async_node->proxy_id);
861
862         transfer_watched_list = g_list_remove(transfer_watched_list,
863                                                         async_node);
864
865         g_object_unref(async_node->proxy);
866         if (async_node->path)
867                 g_free(async_node->path);
868         g_free(async_node);
869 }
870
871 static void simple_cancle_cb(GObject *object,
872                         GAsyncResult *res, gpointer user_data)
873 {
874         GError *error;
875         GVariant *result;
876         GDBusConnection *conn = user_data;
877
878         DBG("");
879
880         error = NULL;
881         result = g_dbus_connection_call_finish(conn, res, &error);
882
883         if (error) {
884                 ERROR("create session error %s", error->message);
885                 g_error_free(error);
886         } else
887                 g_variant_unref(result);
888 }
889
890 void obex_transfer_cancel(const char *path)
891 {
892         GDBusConnection *connection = _obex_get_session_dbus();
893
894         DBG("");
895
896         if (!connection)
897                 return;
898
899         if (path == NULL)
900                 return;
901
902         DBG("path = %s", path);
903
904         g_dbus_connection_call(connection, "org.bluez.obex",
905                                 path,
906                                 "org.bluez.obex.Transfer1",
907                                 "Cancel",
908                                 NULL,
909                                 NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL,
910                                 simple_cancle_cb, connection);
911 }
912
913 static char *_obex_transfer_get_property_session(const char *path)
914 {
915         char *session = NULL;
916         GDBusProxy *p_proxy;
917
918         DBG("");
919
920         p_proxy = g_dbus_proxy_new_for_bus_sync(
921                                         G_BUS_TYPE_SESSION, 0,
922                                         NULL,
923                                         "org.bluez.obex",
924                                         path,
925                                         PROPERTIES_INTERFACE,
926                                         NULL, NULL);
927
928         if (p_proxy)
929                 session = property_get_string(p_proxy,
930                         OBEX_TRANSFER_INTERFACE, "Session");
931
932         g_object_unref(p_proxy);
933
934         return session;
935 }
936
937 char *obex_transfer_get_property_source(const char *path)
938 {
939         char *source = NULL, *session;
940         GDBusProxy *p_proxy;
941
942         DBG("");
943
944         session = _obex_transfer_get_property_session(path);
945
946         DBG("session = %s", session);
947
948         p_proxy = g_dbus_proxy_new_for_bus_sync(
949                                         G_BUS_TYPE_SESSION, 0,
950                                         NULL,
951                                         "org.bluez.obex",
952                                         session,
953                                         PROPERTIES_INTERFACE,
954                                         NULL, NULL);
955
956         if (p_proxy)
957                 source = property_get_string(p_proxy,
958                         OBEX_SESSION_INTERFACE, "Source");
959
960         g_object_unref(p_proxy);
961
962         return source;
963 }
964
965 char *obex_transfer_get_property_destination(const char *path)
966 {
967         char *dest = NULL, *session;
968         GDBusProxy *p_proxy;
969
970         session = _obex_transfer_get_property_session(path);
971
972         DBG("session = %s, path = %s", session, path);
973
974         p_proxy = g_dbus_proxy_new_for_bus_sync(
975                                         G_BUS_TYPE_SESSION, 0,
976                                         NULL,
977                                         "org.bluez.obex",
978                                         session,
979                                         PROPERTIES_INTERFACE,
980                                         NULL, NULL);
981
982         if (p_proxy)
983                 dest = property_get_string(p_proxy,
984                         OBEX_SESSION_INTERFACE, "Destination");
985
986         g_object_unref(p_proxy);
987
988         return dest;
989 }
990
991 char *obex_transfer_get_property_file_name(const char *path)
992 {
993         char *name = NULL;
994         GDBusProxy *p_proxy;
995
996         p_proxy = g_dbus_proxy_new_for_bus_sync(
997                                         G_BUS_TYPE_SESSION, 0,
998                                         NULL,
999                                         "org.bluez.obex",
1000                                         path,
1001                                         PROPERTIES_INTERFACE,
1002                                         NULL, NULL);
1003
1004         if (p_proxy)
1005                 name = property_get_string(p_proxy,
1006                         OBEX_TRANSFER_INTERFACE, "Filename");
1007
1008         g_object_unref(p_proxy);
1009
1010         return name;
1011 }
1012
1013 char *obex_transfer_get_property_name(const char *path)
1014 {
1015         char *name = NULL;
1016         GDBusProxy *p_proxy;
1017
1018         DBG("path = %s", path);
1019
1020         p_proxy = g_dbus_proxy_new_for_bus_sync(
1021                                         G_BUS_TYPE_SESSION, 0,
1022                                         NULL,
1023                                         "org.bluez.obex",
1024                                         path,
1025                                         PROPERTIES_INTERFACE,
1026                                         NULL, NULL);
1027
1028         if (p_proxy)
1029                 name = property_get_string(p_proxy,
1030                         OBEX_TRANSFER_INTERFACE, "Name");
1031
1032         g_object_unref(p_proxy);
1033
1034         return name;
1035 }