Merge the code from private
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-opp-client.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 <mime_type.h>
22 #include <aul.h>
23 #include <glib.h>
24 #include <gio/gio.h>
25
26 #include "bluetooth-api.h"
27 #include "bt-internal-types.h"
28
29 #include "bt-service-common.h"
30 #include "bt-service-event.h"
31 #include "bt-service-util.h"
32 #include "bt-service-opp-client.h"
33 #include "bt-service-obex-agent.h"
34 #include "bt-service-adapter.h"
35
36 #define BT_MIME_TYPE_MAX_LEN    20
37
38 static GSList *transfer_list = NULL;
39 bt_sending_info_t *sending_info;
40 static int file_offset = 0;
41
42 #define DBUS_TIEMOUT 20 * 1000  /* 20 Seconds */
43 static gboolean __bt_sending_release();
44 static int _bt_remove_session();
45
46 static int __bt_opp_client_start_sending(int request_id, char *address,
47                                         char **file_name_array, int file_count);
48
49 static GQuark __bt_opc_error_quark(void)
50 {
51         static GQuark quark = 0;
52         if (!quark)
53                 quark = g_quark_from_static_string("agent");
54
55         return quark;
56 }
57
58 static void __bt_free_transfer_info(bt_transfer_info_t *info)
59 {
60         ret_if(info == NULL);
61
62         if (info->proxy)
63                 g_object_unref(info->proxy);
64
65         if (info->properties_proxy)
66                 g_object_unref(info->properties_proxy);
67
68
69         g_free(info->transfer_name);
70         g_free(info->file_name);
71         g_free(info);
72 }
73
74 static void __bt_free_sending_info(bt_sending_info_t *info)
75 {
76         ret_if(info == NULL);
77
78         /* Free the sending variable */
79         __bt_free_transfer_info(info->transfer_info);
80
81         g_free(info->file_name_array);
82
83         g_free(info->address);
84         g_free(info);
85 }
86
87 static gboolean __bt_cancel_push_cb(gpointer data)
88 {
89         BT_DBG("+");
90
91         int result = BLUETOOTH_ERROR_CANCEL_BY_USER;
92         GVariant *param = NULL;
93         retv_if(sending_info == NULL, FALSE);
94         sending_info->result = result;
95
96         param = g_variant_new("(isi)", result,
97                                 sending_info->address,
98                                 sending_info->request_id);
99         /* Send the event in only error none case */
100         _bt_send_event(BT_OPP_CLIENT_EVENT,
101                         BLUETOOTH_EVENT_OPC_CONNECTED,
102                         param);
103         __bt_free_sending_info(sending_info);
104         sending_info = NULL;
105
106         _bt_opp_client_event_deinit();
107
108         BT_DBG("Length of transfer list is %d", g_slist_length(transfer_list));
109
110          /*Operate remain works*/
111         if (g_slist_length(transfer_list) > 0) {
112                 bt_sending_data_t *node = NULL;
113
114                 node = transfer_list->data;
115                 if (node == NULL) {
116                         BT_ERR("data is NULL");
117                         return FALSE;
118                 }
119
120                 transfer_list = g_slist_remove(transfer_list, node);
121
122                 if (__bt_opp_client_start_sending(node->request_id,
123                                 node->address, node->file_path,
124                                 node->file_count) != BLUETOOTH_ERROR_NONE) {
125                         BT_ERR("Fail to start sending");
126                 }
127         }
128         BT_DBG("-");
129         return FALSE;
130 }
131
132 gboolean _bt_obex_client_progress(const char *transfer_path, guint64 transferred)
133 {
134         BT_DBG("+");
135
136         int percentage_progress;
137         int previous_progress;
138         guint64 size;
139         int result = BLUETOOTH_ERROR_NONE;
140         GVariant *param = NULL;
141         retv_if(sending_info == NULL, TRUE);
142         retv_if(sending_info->transfer_info == NULL, TRUE);
143
144         if (g_strcmp0(sending_info->transfer_info->transfer_path,
145                         transfer_path) != 0) {
146                 BT_INFO("Path mismatch, previous transfer failed! Returning");
147                 return FALSE;
148         }
149
150         size = sending_info->transfer_info->size;
151         if (size != 0)
152                 percentage_progress = (int)(((gdouble)transferred /(gdouble)size) * 100);
153         else
154                 percentage_progress = 0;
155
156         sending_info->transfer_info->transfer_status = BT_TRANSFER_STATUS_PROGRESS;
157         sending_info->result = result;
158
159         previous_progress = (int)(((gdouble)sending_info->transfer_info->progress /(gdouble)size) * 100);
160         if (percentage_progress == previous_progress &&
161                                                         sending_info->transfer_info->progress) {
162                 sending_info->transfer_info->progress = transferred;
163                 return TRUE;
164         }
165                 BT_DBG("Sending progress [prev %d] [curr %d]",
166                                                         previous_progress, percentage_progress);
167
168         sending_info->transfer_info->progress = transferred;
169
170         /* Send the event in only error none case */
171         param = g_variant_new("(istii)", result,
172                                 sending_info->transfer_info->file_name,
173                                 sending_info->transfer_info->size,
174                                 percentage_progress,
175                                 sending_info->request_id);
176
177
178         _bt_send_event(BT_OPP_CLIENT_EVENT,
179                         BLUETOOTH_EVENT_OPC_TRANSFER_PROGRESS,
180                         param);
181         BT_DBG("-");
182
183         return TRUE;
184 }
185
186 gboolean _bt_obex_client_completed(const char *transfer_path, gboolean success)
187 {
188         BT_DBG("+");
189
190         int result = BLUETOOTH_ERROR_NONE;
191         GVariant *param = NULL;
192         retv_if(sending_info == NULL, TRUE);
193         retv_if(sending_info->transfer_info == NULL, TRUE);
194
195         if (g_strcmp0(sending_info->transfer_info->transfer_path,
196                         transfer_path) != 0) {
197                 BT_INFO("Path mismatch, previous transfer failed! Returning");
198                 return FALSE;
199         }
200
201         result = (success == TRUE) ? BLUETOOTH_ERROR_NONE : BLUETOOTH_ERROR_CANCEL;
202
203         sending_info->transfer_info->transfer_status = BT_TRANSFER_STATUS_COMPLETED;
204         sending_info->result = result;
205
206         if (!success) { /*In case of remote device reject, we need to send BLUETOOTH_EVENT_OPC_DISCONNECTED */
207                 BT_DBG("completed with error");
208                 if (!sending_info->is_canceled) {
209                         param = g_variant_new("(issti)", result,
210                                                 sending_info->address,
211                                                 sending_info->transfer_info->file_name,
212                                                 sending_info->transfer_info->size,
213                                                 sending_info->request_id);
214                         _bt_send_event(BT_OPP_CLIENT_EVENT,
215                                         BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE,
216                                         param);
217                    __bt_free_transfer_info(sending_info->transfer_info);
218                    sending_info->transfer_info = NULL;
219                    /* Reset the file offset as we will cancelled remaining files also */
220                    file_offset = 0;
221                 }
222                 param = g_variant_new("(isi)", sending_info->result,
223                                         sending_info->address,
224                                         sending_info->request_id);
225                 _bt_send_event(BT_OPP_CLIENT_EVENT,
226                                 BLUETOOTH_EVENT_OPC_DISCONNECTED,
227                                 param);
228                 __bt_sending_release();
229                 /* Sending info should not freed after sending_release it's
230                  * already freed in that API and if any pending request is
231                  * present then it recreate sending_info again.
232                  * And if we free it here then CreateSession method call will
233                  * made but RemoveSession method call will not done.
234                  */
235         } else {
236                 BT_DBG("complete success");
237                 /* Send the event in only error none case */
238                 param = g_variant_new("(issti)", result,
239                                         sending_info->address,
240                                         sending_info->transfer_info->file_name,
241                                         sending_info->transfer_info->size,
242                                         sending_info->request_id);
243                 _bt_send_event(BT_OPP_CLIENT_EVENT,
244                                 BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE,
245                                 param);
246            __bt_free_transfer_info(sending_info->transfer_info);
247            sending_info->transfer_info = NULL;
248         }
249
250         BT_DBG("-");
251
252         return TRUE;
253 }
254
255 gboolean _bt_obex_client_started(const char *transfer_path)
256 {
257         BT_DBG("+");
258
259         int result = BLUETOOTH_ERROR_NONE;
260         GError *error = NULL;
261         GVariant *param = NULL;
262         GDBusConnection *g_conn;
263         GDBusProxy *properties_proxy;
264         GDBusProxy *transfer_proxy;
265
266         if (sending_info == NULL || sending_info->is_canceled == TRUE) {
267                 result = BLUETOOTH_ERROR_CANCEL_BY_USER;
268                 goto canceled;
269         }
270
271         /* Get the session bus. */
272         g_conn = _bt_gdbus_get_session_gconn();
273         retv_if(g_conn == NULL, FALSE);
274         properties_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
275                                                 NULL, BT_OBEXD_DBUS_NAME,
276                                                 transfer_path, BT_PROPERTIES_INTERFACE,
277                                                 NULL, &error);
278
279         retv_if(properties_proxy == NULL, FALSE);
280
281         sending_info->transfer_info->properties_proxy = properties_proxy;
282
283         transfer_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
284                                                 NULL, BT_OBEXD_DBUS_NAME,
285                                                 transfer_path, BT_OBEX_TRANSFER_INTERFACE,
286                                                 NULL, &error);
287
288         retv_if(transfer_proxy == NULL, FALSE);
289
290         sending_info->transfer_info->proxy = transfer_proxy;
291
292         sending_info->transfer_info->transfer_status = BT_TRANSFER_STATUS_STARTED;
293         sending_info->result = result;
294
295         param = g_variant_new("(issti)", result,
296                                 sending_info->address,
297                                 sending_info->transfer_info->file_name,
298                                 sending_info->transfer_info->size,
299                                 sending_info->request_id);
300         _bt_send_event(BT_OPP_CLIENT_EVENT,
301                         BLUETOOTH_EVENT_OPC_TRANSFER_STARTED,
302                         param);
303
304         BT_DBG("-");
305         return TRUE;
306 canceled:
307         error = g_error_new(__bt_opc_error_quark(), BT_OBEX_AGENT_ERROR_CANCEL,
308                         "CancelledByUser");
309
310         g_error_free(error);
311
312         BT_DBG("-");
313         return FALSE;
314 }
315
316 static void __bt_free_sending_data(gpointer data)
317 {
318         int i;
319         bt_sending_data_t *info = data;
320
321         ret_if(info == NULL);
322
323         for (i = 0; i < info->file_count; i++) {
324                 g_free(info->file_path[i]);
325         }
326
327         _bt_delete_request_id(info->request_id);
328
329         g_free(info->file_path);
330         g_free(info->address);
331         g_free(info);
332 }
333
334 static void __bt_sending_release_cb(GDBusProxy *proxy,
335                                 GAsyncResult *res, gpointer user_data)
336 {
337         BT_DBG("+");
338         ret_if(sending_info == NULL);
339
340         GError *error = NULL;
341         int result = BLUETOOTH_ERROR_NONE;
342         GVariant *param = NULL;
343         GVariant *reply = NULL;
344
345         reply = g_dbus_proxy_call_finish(proxy, res, &error);
346         if (proxy)
347                 g_object_unref(proxy);
348         if (reply)
349                 g_variant_unref(reply);
350
351         if (error) {
352                 BT_ERR("%s", error->message);
353                 g_error_free(error);
354
355                 result = BLUETOOTH_ERROR_INTERNAL;
356         } else {
357                 file_offset = 0;
358                 BT_DBG("Session Removed");
359         }
360
361         sending_info->result = result;
362         param = g_variant_new("(isi)", sending_info->result,
363                                 sending_info->address,
364                                 sending_info->request_id);
365         /* Send the event in only error none case */
366         _bt_send_event(BT_OPP_CLIENT_EVENT,
367                         BLUETOOTH_EVENT_OPC_DISCONNECTED,
368                         param);
369
370         __bt_free_sending_info(sending_info);
371         sending_info = NULL;
372
373         _bt_opp_client_event_deinit();
374
375         /* Operate remain works */
376         if (g_slist_length(transfer_list) > 0) {
377                 bt_sending_data_t *data = NULL;
378
379                 data = transfer_list->data;
380                 if (data == NULL)
381                         goto fail;
382
383                 transfer_list = g_slist_remove(transfer_list, data);
384
385                 BT_DBG("calling __bt_opp_client_start_sending");
386
387                 if (__bt_opp_client_start_sending(data->request_id,
388                                 data->address, data->file_path,
389                                 data->file_count) != BLUETOOTH_ERROR_NONE) {
390                         goto fail;
391                 }
392         }
393
394         return;
395 fail:
396         g_slist_free_full(transfer_list,
397                                 (GDestroyNotify)__bt_free_sending_data);
398         transfer_list = NULL;
399
400         BT_DBG("-");
401
402         return;
403 }
404
405 static int _bt_remove_session()
406 {
407         GDBusConnection *g_conn;
408         GDBusProxy *session_proxy;
409         GError *err = NULL;
410
411         g_conn = _bt_gdbus_get_session_gconn();
412         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
413         retv_if(sending_info->session_path == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
414
415         session_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
416                                                 NULL, BT_OBEXD_DBUS_NAME,
417                                                 BT_OBEX_CLIENT_PATH,
418                                                 BT_OBEX_CLIENT_INTERFACE,
419                                                 NULL, &err);
420
421         retv_if(session_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
422
423         g_dbus_proxy_call(session_proxy, "RemoveSession",
424                 g_variant_new("(o)", sending_info->session_path),
425                 G_DBUS_CALL_FLAGS_NONE,
426                 DBUS_TIEMOUT, NULL,
427                 (GAsyncReadyCallback)__bt_sending_release_cb,
428                 NULL);
429
430         return BLUETOOTH_ERROR_NONE;
431 }
432
433 static gboolean __bt_sending_release()
434 {
435         BT_DBG("+");
436
437         retv_if(sending_info == NULL, FALSE);
438
439         retv_if(_bt_remove_session() != BLUETOOTH_ERROR_NONE, FALSE);
440
441         BT_DBG("-");
442         return TRUE;
443 }
444
445 void _bt_opc_disconnected(const char *session_path)
446 {
447         BT_DBG("+");
448         GVariant *param = NULL;
449         ret_if(sending_info == NULL);
450
451         if (g_strcmp0(sending_info->session_path,
452                         session_path) != 0) {
453                 BT_INFO("Path mismatch, previous transfer failed! Returning");
454                 return;
455         }
456
457         if (sending_info->transfer_info) {
458                 if (sending_info->transfer_info->transfer_status == BT_TRANSFER_STATUS_PROGRESS ||
459                                 sending_info->transfer_info->transfer_status == BT_TRANSFER_STATUS_STARTED) {
460                         BT_INFO("Abnormal termination");
461                         param = g_variant_new("(issti)", sending_info->result,
462                                                 sending_info->address,
463                                                 sending_info->transfer_info->file_name,
464                                                 sending_info->transfer_info->size,
465                                                 sending_info->request_id);
466                         _bt_send_event(BT_OPP_CLIENT_EVENT,
467                                         BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE,
468                                         param);
469                         __bt_free_transfer_info(sending_info->transfer_info);
470                 }
471         }
472         param = g_variant_new("(isi)", sending_info->result,
473                                 sending_info->address,
474                                 sending_info->request_id);
475         _bt_send_event(BT_OPP_CLIENT_EVENT,
476                         BLUETOOTH_EVENT_OPC_DISCONNECTED,
477                         param);
478
479         __bt_free_sending_info(sending_info);
480         sending_info = NULL;
481
482         BT_DBG("-");
483 }
484
485 static void __bt_send_file_cb(GDBusProxy *proxy,
486                                 GAsyncResult *res, gpointer user_data)
487 {
488         BT_DBG("+");
489         GVariant *value = NULL;
490         GError *error = NULL;
491         char *session_path = NULL;
492         const char *transfer_name = NULL;
493         const char *file_name = NULL;
494         int size = 0;
495         GVariantIter *iter = NULL;
496         value = g_dbus_proxy_call_finish(proxy, res, &error);
497         if (error) {
498                 g_dbus_error_strip_remote_error(error);
499                 BT_ERR("%s", error->message);
500                 /* If Obex is not able to open a file then continue with other if any */
501                 if (g_strcmp0("Unable to open file", error->message) == 0) {
502                         GVariant *param = NULL;
503                         gint64 size = 0;
504
505                         BT_ERR("Unable to open file [%s]", sending_info->file_name_array[file_offset]);
506
507                         param = g_variant_new("(issti)", BLUETOOTH_ERROR_NOT_FOUND,
508                                         sending_info->address,
509                                         sending_info->file_name_array[file_offset],
510                                         size,
511                                         sending_info->request_id);
512                         _bt_send_event(BT_OPP_CLIENT_EVENT,
513                                         BLUETOOTH_EVENT_OPC_TRANSFER_STARTED,
514                                         param);
515
516                         param = g_variant_new("(issti)", BLUETOOTH_ERROR_NOT_FOUND,
517                                                 sending_info->address,
518                                                 sending_info->file_name_array[file_offset],
519                                                 size,
520                                                 sending_info->request_id);
521                         _bt_send_event(BT_OPP_CLIENT_EVENT,
522                                         BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE,
523                                         param);
524                         g_error_free(error);
525                         if (proxy)
526                                 g_object_unref(proxy);
527                         file_offset++;
528                         _bt_sending_files();
529                 }
530                 return;
531         }
532         if (proxy)
533                 g_object_unref(proxy);
534
535         if (value) {
536                 g_variant_get(value, "(oa{sv})", &session_path, &iter);
537                 g_variant_unref(value);
538         }
539
540         __bt_free_transfer_info(sending_info->transfer_info);
541
542         sending_info->transfer_info = g_malloc0(sizeof(bt_transfer_info_t));
543
544         if (iter) {
545                 const gchar *key;
546                 GVariant *val;
547                 gsize len = 0;
548                 while (g_variant_iter_loop(iter, "{sv}", &key, &val)) {
549                         if (g_strcmp0(key, "Name") == 0) {
550                                 transfer_name = g_variant_dup_string(val, &len);
551                         } else if (g_strcmp0(key, "Filename") == 0) {
552                                 file_name = g_variant_dup_string(val, &len);
553                         } else if (g_strcmp0(key, "Size") == 0) {
554                                 size = g_variant_get_uint64(val);
555                         }
556                 }
557                 g_variant_iter_free(iter);
558         }
559
560         sending_info->transfer_info->transfer_name = g_strdup(transfer_name);
561         sending_info->transfer_info->file_name = g_strdup(file_name);
562         sending_info->transfer_info->size = size;
563         sending_info->transfer_info->progress = 0;
564         sending_info->transfer_info->transfer_path = session_path;
565         sending_info->transfer_info->transfer_status = BT_TRANSFER_STATUS_QUEUED;
566         sending_info->result = BLUETOOTH_ERROR_NONE;
567         file_offset++;
568
569         g_free((gchar *)transfer_name);
570         g_free((gchar *)file_name);
571 }
572
573 void _bt_sending_files(void)
574 {
575         BT_DBG("+");
576
577         GError *err = NULL;
578         GDBusConnection *g_conn;
579         GDBusProxy *client_proxy;
580         char mime_type[BT_MIME_TYPE_MAX_LEN + 1] = { 0 };
581
582         if (sending_info == NULL)
583                 return;
584         if (file_offset < sending_info->file_count) {
585                 /* Get the session bus. */
586                 g_conn = _bt_gdbus_get_session_gconn();
587                 ret_if(g_conn == NULL);
588
589                 client_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
590                                                 NULL, BT_OBEXD_DBUS_NAME,
591                                                 sending_info->session_path,
592                                                 BT_OBEX_OBJECT_PUSH_INTERFACE,
593                                                 NULL, &err);
594                 ret_if(client_proxy == NULL);
595                 if (aul_get_mime_from_file(sending_info->file_name_array[file_offset],
596                                 mime_type, BT_MIME_TYPE_MAX_LEN) == AUL_R_OK) {
597                                 BT_DBG("MLME type = %s", mime_type);
598
599                                 /* For IOPT compliance, change "text/x-iMelody" to "audio/imelody"
600                                  * because few devices(multimedia players) reject the OPP put for text objects
601                                  * since they support only multimedia files exchange */
602                                 if (!strcasecmp(mime_type, "text/x-iMelody")) {
603                                         strncpy(mime_type, "audio/imelody", BT_MIME_TYPE_MAX_LEN);
604                                         BT_DBG("over writing mime type to  = %s", mime_type);
605                                 }
606                                 if (!strcasecmp(mime_type, "text/vcard")) {
607                                         strncpy(mime_type, "text/x-vcard", BT_MIME_TYPE_MAX_LEN);
608                                         BT_DBG("over writing mime type to  = %s", mime_type);
609                                 }
610                 }
611
612                 BT_DBG("Calling SendFile");
613                 g_dbus_proxy_call(client_proxy, "SendFile",
614                                 g_variant_new("(ss)", sending_info->file_name_array[file_offset],
615                                                                 mime_type),
616                                 G_DBUS_CALL_FLAGS_NONE,
617                                 DBUS_TIEMOUT, NULL,
618                                 (GAsyncReadyCallback)__bt_send_file_cb,
619                                 sending_info);
620                 if (err != NULL) {
621                         BT_ERR("Calling SendFile failed: [%s]\n", err->message);
622                         g_clear_error(&err);
623                         return;
624                 }
625
626         } else {
627                 file_offset = 0;
628                 __bt_sending_release();
629         }
630
631         BT_DBG("-");
632 }
633
634 static void __bt_create_session_cb(GDBusProxy *proxy,
635                                 GAsyncResult *res, gpointer user_data)
636 {
637         BT_DBG("+");
638
639         GError *error = NULL;
640         GVariant *value;
641         int result = BLUETOOTH_ERROR_NONE;
642         char *session_path = NULL;
643         GVariant *param = NULL;
644
645         value = g_dbus_proxy_call_finish(proxy, res, &error);
646         if (value) {
647                 g_variant_get(value, "(o)", &session_path);
648                 g_variant_unref(value);
649         }
650         if (error) {
651
652                 BT_ERR("%s", error->message);
653                 g_clear_error(&error);
654
655                 result = BLUETOOTH_ERROR_INTERNAL;
656         } else {
657                 BT_DBG("Session created");
658                 if (sending_info != NULL)
659                         sending_info->session_path = g_strdup(session_path);
660         }
661         g_free(session_path);
662         g_object_unref(proxy);
663         ret_if(sending_info == NULL);
664
665         sending_info->result = result;
666         param = g_variant_new("(isi)", result,
667                                 sending_info->address,
668                                 sending_info->request_id);
669         /* Send the event in only error none case */
670         _bt_send_event(BT_OPP_CLIENT_EVENT,
671                         BLUETOOTH_EVENT_OPC_CONNECTED,
672                         param);
673
674         if (result != BLUETOOTH_ERROR_NONE) {
675                 BT_ERR("Calling __bt_sending_release");
676                 gboolean ret = __bt_sending_release();
677
678                 __bt_free_sending_info(sending_info);
679                 sending_info = NULL;
680
681                 if (ret == FALSE) {
682                         BT_DBG("ReleaseSession Not called");
683                         /* Operate remain works */
684                         if (g_slist_length(transfer_list) > 0) {
685                                 bt_sending_data_t *data = NULL;
686
687                                 data = transfer_list->data;
688                                 ret_if(data == NULL);
689
690                                 transfer_list = g_slist_remove(transfer_list, data);
691
692                                 BT_DBG("calling __bt_opp_client_start_sending");
693
694                                 if (__bt_opp_client_start_sending(data->request_id,
695                                                 data->address, data->file_path,
696                                                 data->file_count) != BLUETOOTH_ERROR_NONE) {
697                                         BT_ERR("Sending Enqueued Transfer Failed");
698                                 }
699                         }
700                 }
701         } else {
702                 BT_DBG("Calling sending_files");
703                 _bt_sending_files();
704         }
705         BT_DBG("-");
706
707 }
708
709 static int __bt_opp_client_start_sending(int request_id, char *address,
710                                         char **file_name_array, int file_count)
711 {
712         GVariantBuilder *builder;
713         int i;
714         GDBusConnection *g_conn;
715         GDBusProxy *client_proxy;
716         GError *error = NULL;
717         BT_DBG("+");
718
719         BT_CHECK_PARAMETER(address, return);
720         BT_CHECK_PARAMETER(file_name_array, return);
721
722         /* Get the session bus. */
723         g_conn = _bt_gdbus_get_session_gconn();
724         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
725
726         client_proxy =  g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
727                                         NULL, BT_OBEX_SERVICE_NAME,
728                                         BT_OBEX_CLIENT_PATH,
729                                         BT_OBEX_CLIENT_INTERFACE,
730                                         NULL, &error);
731
732         if (error) {
733                 BT_ERR("Unable to create client proxy: %s", error->message);
734                 g_clear_error(&error);
735         }
736
737         retv_if(client_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
738
739         builder = g_variant_builder_new(
740                                 G_VARIANT_TYPE("a{sv}"));
741
742         g_variant_builder_add(builder, "{sv}", "Target",
743                 g_variant_new_string("OPP"));
744
745         __bt_free_sending_info(sending_info);
746
747         sending_info = g_malloc0(sizeof(bt_sending_info_t));
748         sending_info->address = g_strdup(address);
749         sending_info->request_id = request_id;
750
751         sending_info->file_count = file_count;
752         sending_info->file_offset = 0;
753         sending_info->file_name_array = g_new0(char *, file_count + 1);
754
755         for (i = 0; i < file_count; i++) {
756                 sending_info->file_name_array[i] = g_strdup(file_name_array[i]);
757                 BT_DBG("file[%d]: %s", i, sending_info->file_name_array[i]);
758         }
759
760         _bt_opp_client_event_deinit();
761         _bt_opp_client_event_init();
762         //_bt_obex_client_started(agent_path);
763
764         BT_DBG("Adapter Status %d", _bt_adapter_get_status());
765         if (_bt_adapter_get_status() == BT_ACTIVATED) {
766                 BT_DBG("Going to call CreateSession");
767                 g_dbus_proxy_call(client_proxy, "CreateSession",
768                                                 g_variant_new("(sa{sv})", address, builder),
769                                                 G_DBUS_CALL_FLAGS_NONE,
770                                                 DBUS_TIEMOUT, NULL,
771                                                 (GAsyncReadyCallback)__bt_create_session_cb,
772                                                 NULL);
773         } else {
774                 GVariant *param = g_variant_new("(isi)", BLUETOOTH_ERROR_INTERNAL,
775                                 sending_info->address, sending_info->request_id);
776
777                 BT_DBG("Address[%s] RequestID[%d]", sending_info->address, sending_info->request_id);
778                 _bt_send_event(BT_OPP_CLIENT_EVENT, BLUETOOTH_EVENT_OPC_CONNECTED,
779                                                                         param);
780                 __bt_free_sending_info(sending_info);
781                 sending_info = NULL;
782         }
783         g_variant_builder_unref(builder);
784
785         BT_DBG("-");
786
787         return BLUETOOTH_ERROR_NONE;
788 }
789
790 int _bt_opp_client_push_files(int request_id, GDBusMethodInvocation *context,
791                                 bluetooth_device_address_t *remote_address,
792                                 char **file_path, int file_count)
793 {
794         BT_DBG("+");
795         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
796         bt_sending_data_t *data;
797
798         GVariant *out_param1 = NULL;
799
800         int result = BLUETOOTH_ERROR_NONE;
801         int i;
802
803         BT_CHECK_PARAMETER(remote_address, return);
804         BT_CHECK_PARAMETER(file_path, return);
805
806         /* Implement the queue */
807         _bt_convert_addr_type_to_string(address, remote_address->addr);
808
809         if (sending_info == NULL) {
810                 result = __bt_opp_client_start_sending(request_id,
811                                                 address, file_path, file_count);
812                 if (result != BLUETOOTH_ERROR_NONE)
813                         return result;
814         } else {
815                 /* Insert data in the queue */
816                 data = g_malloc0(sizeof(bt_sending_data_t));
817                 if (data == NULL)
818                         return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
819
820                 data->file_path = g_new0(char *, file_count + 1);
821                 data->address = g_strdup(address);
822                 data->file_count = file_count;
823                 data->request_id = request_id;
824
825                 for (i = 0; i < file_count; i++) {
826                         data->file_path[i] = g_strdup(file_path[i]);
827                         DBG_SECURE("file[%d]: %s", i, data->file_path[i]);
828                 }
829
830                 transfer_list = g_slist_append(transfer_list, data);
831         }
832
833         out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
834                                                         &request_id, sizeof(int),
835                                                         TRUE, NULL, NULL);
836
837
838         g_dbus_method_invocation_return_value(context,
839                         g_variant_new("(iv)", result, out_param1));
840
841         BT_DBG("-");
842
843         return result;
844 }
845
846 int _bt_opp_client_cancel_push(void)
847 {
848         BT_DBG("+");
849
850         GError *err = NULL;
851         int result = BLUETOOTH_ERROR_CANCEL_BY_USER;
852         GVariant *ret = NULL;
853         GVariant *param = NULL;
854         retv_if(sending_info == NULL, BLUETOOTH_ERROR_NOT_IN_OPERATION);
855
856         sending_info->is_canceled = TRUE;
857         sending_info->result = result;
858
859         if (sending_info->transfer_info) {
860
861                 ret = g_dbus_proxy_call_sync(sending_info->transfer_info->proxy,
862                                         "Cancel", NULL,
863                                         G_DBUS_CALL_FLAGS_NONE, -1,
864                                         NULL, &err);
865                 if (ret == NULL) {
866                         if (err != NULL) {
867                                 BT_ERR("Cancel Error: %s\n", err->message);
868                                 g_error_free(err);
869                         }
870                 } else {
871                         g_variant_unref(ret);
872                 }
873
874                 param = g_variant_new("(issti)", result,
875                                         sending_info->address,
876                                         sending_info->transfer_info->file_name,
877                                         sending_info->transfer_info->size,
878                                         sending_info->request_id);
879                 _bt_send_event(BT_OPP_CLIENT_EVENT,
880                                 BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE,
881                                 param);
882
883                 if (result == BLUETOOTH_ERROR_CANCEL_BY_USER) {
884                         BT_ERR("result is not BLUETOOTH_ERROR_NONE");
885                         __bt_sending_release();
886                         file_offset = 0;
887                 }
888
889         } else {
890                 g_idle_add(__bt_cancel_push_cb, NULL);
891         }
892
893         BT_DBG("-");
894
895         return BLUETOOTH_ERROR_NONE;
896 }
897
898 int _bt_opp_client_cancel_all_transfers(void)
899 {
900         BT_DBG("+");
901         if (transfer_list) {
902                 g_slist_free_full(transfer_list,
903                         (GDestroyNotify)__bt_free_sending_data);
904
905                 transfer_list = NULL;
906         }
907
908         _bt_opp_client_cancel_push();
909         BT_DBG("-");
910         return BLUETOOTH_ERROR_NONE;
911 }
912
913 int _bt_opp_client_is_sending(gboolean *sending)
914 {
915         BT_CHECK_PARAMETER(sending, return);
916
917         *sending = sending_info ? TRUE : FALSE;
918
919         return BLUETOOTH_ERROR_NONE;
920 }
921
922 void _bt_opp_client_check_pending_transfer(const char *address)
923 {
924         BT_DBG("+");
925
926         int result = BLUETOOTH_ERROR_CANCEL;
927         GVariant *param = NULL;
928         ret_if(sending_info == NULL);
929         ret_if(sending_info->transfer_info == NULL);
930
931         if (g_strcmp0(sending_info->address, address) == 0) {
932                 BT_INFO("Address Match.Cancel current transfer");
933                 sending_info->transfer_info->transfer_status = BT_TRANSFER_STATUS_COMPLETED;
934                 sending_info->result = result;
935
936                 if (!sending_info->is_canceled) {
937                         param = g_variant_new("(issti)", result,
938                                                 sending_info->address,
939                                                 sending_info->transfer_info->file_name,
940                                                 sending_info->transfer_info->size,
941                                                 sending_info->request_id);
942                         _bt_send_event(BT_OPP_CLIENT_EVENT,
943                                         BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE,
944                                         param);
945                         __bt_free_transfer_info(sending_info->transfer_info);
946                         sending_info->transfer_info = NULL;
947                         /* Reset the file offset as we will cancelled remaining files also */
948                         file_offset = 0;
949                 }
950                 param = g_variant_new("(isi)", sending_info->result,
951                                         sending_info->address,
952                                         sending_info->request_id);
953                 _bt_send_event(BT_OPP_CLIENT_EVENT,
954                                 BLUETOOTH_EVENT_OPC_DISCONNECTED,
955                                 param);
956
957                 __bt_sending_release();
958         }
959         BT_DBG("-");
960 }
961
962 int _bt_opp_get_client_progress(guint8 *progress)
963 {
964         if (sending_info == NULL || sending_info->transfer_info == NULL) {
965                 BT_ERR("No Active Outbound transfer");
966                 return BLUETOOTH_ERROR_NOT_FOUND;
967         }
968
969         *progress = (int)(((double)sending_info->transfer_info->progress /
970                         sending_info->transfer_info->size) * 100);
971
972         BT_DBG("Percentage: %d", *progress);
973         return BLUETOOTH_ERROR_NONE;
974 }
975
976 void _bt_cancel_queued_transfers(void)
977 {
978         bt_sending_data_t *data = NULL;
979         GVariant *param = NULL;
980
981         BT_INFO("Cancel queued Transfers:: Length of transfer list is %d",
982                                         g_slist_length(transfer_list));
983
984         while (transfer_list) {
985                 data = transfer_list->data;
986                 param = g_variant_new("(isi)", BLUETOOTH_ERROR_INTERNAL,
987                                 data->address, data->request_id);
988
989                 BT_DBG("Address[%s] RequestID[%d]", data->address, data->request_id);
990                 _bt_send_event(BT_OPP_CLIENT_EVENT, BLUETOOTH_EVENT_OPC_CONNECTED,
991                                                                         param);
992
993                 transfer_list = g_slist_remove(transfer_list, data);
994         }
995 }