Don't add the recovery logic into the platform image
[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_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         g_dbus_proxy_call_finish(proxy, res, &error);
344         if (proxy)
345                 g_object_unref(proxy);
346
347         if (error) {
348                 BT_ERR("%s", error->message);
349                 g_error_free(error);
350
351                 result = BLUETOOTH_ERROR_INTERNAL;
352         } else {
353                 file_offset = 0;
354                 BT_DBG("Session Removed");
355         }
356
357         sending_info->result = result;
358         param = g_variant_new("(isi)", sending_info->result,
359                                 sending_info->address,
360                                 sending_info->request_id);
361         /* Send the event in only error none case */
362         _bt_send_event(BT_OPP_CLIENT_EVENT,
363                         BLUETOOTH_EVENT_OPC_DISCONNECTED,
364                         param);
365
366         __bt_free_sending_info(sending_info);
367         sending_info = NULL;
368
369         _bt_opp_client_event_deinit();
370
371         /* Operate remain works */
372         if (g_slist_length(transfer_list) > 0) {
373                 bt_sending_data_t *data = NULL;
374
375                 data = transfer_list->data;
376                 if (data == NULL)
377                         goto fail;
378
379                 transfer_list = g_slist_remove(transfer_list, data);
380
381                 BT_DBG("calling __bt_opp_client_start_sending");
382
383                 if (__bt_opp_client_start_sending(data->request_id,
384                                 data->address, data->file_path,
385                                 data->file_count) != BLUETOOTH_ERROR_NONE) {
386                         goto fail;
387                 }
388         }
389
390         return;
391 fail:
392         g_slist_free_full(transfer_list,
393                                 (GDestroyNotify)__bt_free_sending_data);
394         transfer_list = NULL;
395
396         BT_DBG("-");
397
398         return;
399 }
400
401 static int _bt_remove_session()
402 {
403         GDBusConnection *g_conn;
404         GDBusProxy *session_proxy;
405         GError *err = NULL;
406
407         g_conn = _bt_get_session_gconn();
408         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
409         retv_if(sending_info->session_path == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
410
411         session_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
412                                                 NULL, BT_OBEXD_DBUS_NAME,
413                                                 BT_OBEX_CLIENT_PATH,
414                                                 BT_OBEX_CLIENT_INTERFACE,
415                                                 NULL, &err);
416
417         retv_if(session_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
418
419         g_dbus_proxy_call(session_proxy, "RemoveSession",
420                 g_variant_new("(o)", sending_info->session_path),
421                 G_DBUS_CALL_FLAGS_NONE,
422                 DBUS_TIEMOUT, NULL,
423                 (GAsyncReadyCallback)__bt_sending_release_cb,
424                 NULL);
425
426         return BLUETOOTH_ERROR_NONE;
427 }
428
429 static gboolean __bt_sending_release()
430 {
431         BT_DBG("+");
432
433         retv_if(sending_info == NULL, FALSE);
434
435         retv_if(_bt_remove_session() != BLUETOOTH_ERROR_NONE, FALSE);
436
437         BT_DBG("-");
438         return TRUE;
439 }
440
441 void _bt_opc_disconnected(const char *session_path)
442 {
443         BT_DBG("+");
444         GVariant *param = NULL;
445         ret_if(sending_info == NULL);
446
447         if (g_strcmp0(sending_info->session_path,
448                         session_path) != 0) {
449                 BT_INFO("Path mismatch, previous transfer failed! Returning");
450                 return;
451         }
452
453         if (sending_info->transfer_info) {
454                 if (sending_info->transfer_info->transfer_status == BT_TRANSFER_STATUS_PROGRESS ||
455                                 sending_info->transfer_info->transfer_status == BT_TRANSFER_STATUS_STARTED) {
456                         BT_INFO("Abnormal termination");
457                         param = g_variant_new("(issti)", sending_info->result,
458                                                 sending_info->address,
459                                                 sending_info->transfer_info->file_name,
460                                                 sending_info->transfer_info->size,
461                                                 sending_info->request_id);
462                         _bt_send_event(BT_OPP_CLIENT_EVENT,
463                                         BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE,
464                                         param);
465                         __bt_free_transfer_info(sending_info->transfer_info);
466                 }
467         }
468         param = g_variant_new("(isi)", sending_info->result,
469                                 sending_info->address,
470                                 sending_info->request_id);
471         _bt_send_event(BT_OPP_CLIENT_EVENT,
472                         BLUETOOTH_EVENT_OPC_DISCONNECTED,
473                         param);
474
475         __bt_free_sending_info(sending_info);
476         sending_info = NULL;
477
478         BT_DBG("-");
479 }
480
481 static void __bt_send_file_cb(GDBusProxy *proxy,
482                                 GAsyncResult *res, gpointer user_data)
483 {
484         BT_DBG("+");
485         GVariant *value = NULL;
486         GError *error = NULL;
487         char *session_path = NULL;
488         const char *transfer_name = NULL;
489         const char *file_name = NULL;
490         int size = 0;
491         GVariantIter *iter = NULL;
492         value = g_dbus_proxy_call_finish(proxy, res, &error);
493         if (error) {
494                 g_dbus_error_strip_remote_error(error);
495                 BT_ERR("%s", error->message);
496                 /* If Obex is not able to open a file then continue with other if any */
497                 if (g_strcmp0("Unable to open file", error->message) == 0) {
498                         GVariant *param = NULL;
499                         gint64 size = 0;
500
501                         BT_ERR("Unable to open file [%s]", sending_info->file_name_array[file_offset]);
502
503                         param = g_variant_new("(issti)", BLUETOOTH_ERROR_NOT_FOUND,
504                                         sending_info->address,
505                                         sending_info->file_name_array[file_offset],
506                                         size,
507                                         sending_info->request_id);
508                         _bt_send_event(BT_OPP_CLIENT_EVENT,
509                                         BLUETOOTH_EVENT_OPC_TRANSFER_STARTED,
510                                         param);
511
512                         param = g_variant_new("(issti)", BLUETOOTH_ERROR_NOT_FOUND,
513                                                 sending_info->address,
514                                                 sending_info->file_name_array[file_offset],
515                                                 size,
516                                                 sending_info->request_id);
517                         _bt_send_event(BT_OPP_CLIENT_EVENT,
518                                         BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE,
519                                         param);
520                         g_error_free(error);
521                         if (proxy)
522                                 g_object_unref(proxy);
523                         file_offset++;
524                         _bt_sending_files();
525                 }
526                 return;
527         }
528         if (proxy)
529                 g_object_unref(proxy);
530
531         if (value) {
532                 g_variant_get(value, "(oa{sv})", &session_path, &iter);
533                 g_variant_unref(value);
534         }
535
536         __bt_free_transfer_info(sending_info->transfer_info);
537
538         sending_info->transfer_info = g_malloc0(sizeof(bt_transfer_info_t));
539
540         if (iter) {
541                 const gchar *key;
542                 GVariant *val;
543                 gsize len = 0;
544                 while (g_variant_iter_loop(iter, "{sv}", &key, &val)) {
545                         if (g_strcmp0(key, "Name") == 0) {
546                                 transfer_name = g_variant_dup_string(val, &len);
547                         } else if (g_strcmp0(key, "Filename") == 0) {
548                                 file_name = g_variant_dup_string(val, &len);
549                         } else if (g_strcmp0(key, "Size") == 0) {
550                                 size = g_variant_get_uint64(val);
551                         }
552                 }
553                 g_variant_iter_free(iter);
554         }
555
556         sending_info->transfer_info->transfer_name = g_strdup(transfer_name);
557         sending_info->transfer_info->file_name = g_strdup(file_name);
558         sending_info->transfer_info->size = size;
559         sending_info->transfer_info->progress = 0;
560         sending_info->transfer_info->transfer_path = session_path;
561         sending_info->transfer_info->transfer_status = BT_TRANSFER_STATUS_QUEUED;
562         sending_info->result = BLUETOOTH_ERROR_NONE;
563         file_offset++;
564
565         g_free((gchar *)transfer_name);
566         g_free((gchar *)file_name);
567 }
568
569 void _bt_sending_files(void)
570 {
571         BT_DBG("+");
572
573         GError *err = NULL;
574         GDBusConnection *g_conn;
575         GDBusProxy *client_proxy;
576         char mime_type[BT_MIME_TYPE_MAX_LEN + 1] = { 0 };
577
578         if (sending_info == NULL)
579                 return;
580         if (file_offset < sending_info->file_count) {
581                 /* Get the session bus. */
582                 g_conn = _bt_get_session_gconn();
583                 ret_if(g_conn == NULL);
584
585                 client_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
586                                                 NULL, BT_OBEXD_DBUS_NAME,
587                                                 sending_info->session_path,
588                                                 BT_OBEX_OBJECT_PUSH_INTERFACE,
589                                                 NULL, &err);
590                 ret_if(client_proxy == NULL);
591                 if (aul_get_mime_from_file(sending_info->file_name_array[file_offset],
592                                 mime_type, BT_MIME_TYPE_MAX_LEN) == AUL_R_OK) {
593                                 BT_DBG("MLME type = %s", mime_type);
594
595                                 /* For IOPT compliance, change "text/x-iMelody" to "audio/imelody"
596                                  * because few devices(multimedia players) reject the OPP put for text objects
597                                  * since they support only multimedia files exchange */
598                                 if(!strcasecmp(mime_type, "text/x-iMelody")) {
599                                         strncpy(mime_type, "audio/imelody", BT_MIME_TYPE_MAX_LEN);
600                                         BT_DBG("over writing mime type to  = %s", mime_type);
601                                 }
602                                 if(!strcasecmp(mime_type, "text/vcard")) {
603                                         strncpy(mime_type, "text/x-vcard", BT_MIME_TYPE_MAX_LEN);
604                                         BT_DBG("over writing mime type to  = %s", mime_type);
605                                 }
606                 }
607
608                 BT_DBG("Calling SendFile");
609                 g_dbus_proxy_call(client_proxy, "SendFile",
610                                 g_variant_new("(ss)", sending_info->file_name_array[file_offset],
611                                                                 mime_type),
612                                 G_DBUS_CALL_FLAGS_NONE,
613                                 DBUS_TIEMOUT, NULL,
614                                 (GAsyncReadyCallback)__bt_send_file_cb,
615                                 sending_info);
616                 if (err != NULL) {
617                         BT_ERR("Calling SendFile failed: [%s]\n", err->message);
618                         g_clear_error(&err);
619                         return;
620                 }
621
622         }else{
623                 file_offset = 0;
624                 __bt_sending_release();
625         }
626
627         BT_DBG("-");
628 }
629
630 static void __bt_create_session_cb(GDBusProxy *proxy,
631                                 GAsyncResult *res, gpointer user_data)
632 {
633         BT_DBG("+");
634
635         GError *error = NULL;
636         GVariant *value;
637         int result = BLUETOOTH_ERROR_NONE;
638         char *session_path = NULL;
639         GVariant *param = NULL;
640
641         value = g_dbus_proxy_call_finish(proxy, res, &error);
642         if (value) {
643                 g_variant_get(value, "(o)", &session_path);
644                 g_variant_unref(value);
645         }
646         if (error) {
647
648                 BT_ERR("%s", error->message);
649                 g_clear_error(&error);
650
651                 result = BLUETOOTH_ERROR_INTERNAL;
652         } else {
653                 BT_DBG("Session created");
654                 if (sending_info != NULL)
655                         sending_info->session_path = g_strdup(session_path);
656         }
657         g_free(session_path);
658         g_object_unref(proxy);
659         ret_if(sending_info == NULL);
660
661         sending_info->result = result;
662         param = g_variant_new("(isi)", result,
663                                 sending_info->address,
664                                 sending_info->request_id);
665         /* Send the event in only error none case */
666         _bt_send_event(BT_OPP_CLIENT_EVENT,
667                         BLUETOOTH_EVENT_OPC_CONNECTED,
668                         param);
669
670         if (result != BLUETOOTH_ERROR_NONE) {
671                 BT_ERR("Calling __bt_sending_release");
672                 gboolean ret = __bt_sending_release();
673
674                 __bt_free_sending_info(sending_info);
675                 sending_info = NULL;
676
677                 if (ret == FALSE) {
678                         BT_DBG("ReleaseSession Not called");
679                         /* Operate remain works */
680                         if (g_slist_length(transfer_list) > 0) {
681                                 bt_sending_data_t *data = NULL;
682
683                                 data = transfer_list->data;
684                                 ret_if(data == NULL);
685
686                                 transfer_list = g_slist_remove(transfer_list, data);
687
688                                 BT_DBG("calling __bt_opp_client_start_sending");
689
690                                 if (__bt_opp_client_start_sending(data->request_id,
691                                                 data->address, data->file_path,
692                                                 data->file_count) != BLUETOOTH_ERROR_NONE) {
693                                         BT_ERR("Sending Enqueued Transfer Failed");
694                                 }
695                         }
696                 }
697         } else {
698                 BT_DBG("Calling sending_files");
699                 _bt_sending_files();
700         }
701         BT_DBG("-");
702
703 }
704
705 static int __bt_opp_client_start_sending(int request_id, char *address,
706                                         char **file_name_array, int file_count)
707 {
708         GVariantBuilder *builder;
709         int i;
710         GDBusConnection *g_conn;
711         GDBusProxy *client_proxy;
712         GError *error = NULL;
713         BT_DBG("+");
714
715         BT_CHECK_PARAMETER(address, return);
716         BT_CHECK_PARAMETER(file_name_array, return);
717
718         /* Get the session bus. */
719         g_conn = _bt_get_session_gconn();
720         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
721
722         client_proxy =  g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
723                                         NULL, BT_OBEX_SERVICE_NAME,
724                                         BT_OBEX_CLIENT_PATH,
725                                         BT_OBEX_CLIENT_INTERFACE,
726                                         NULL, &error);
727
728         if (error) {
729                 BT_ERR("Unable to create client proxy: %s", error->message);
730                 g_clear_error(&error);
731         }
732
733         retv_if(client_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
734
735         builder = g_variant_builder_new(
736                                 G_VARIANT_TYPE("a{sv}"));
737
738         g_variant_builder_add(builder, "{sv}", "Target",
739                 g_variant_new_string("OPP"));
740
741         __bt_free_sending_info(sending_info);
742
743         sending_info = g_malloc0(sizeof(bt_sending_info_t));
744         sending_info->address = g_strdup(address);
745         sending_info->request_id = request_id;
746
747         sending_info->file_count = file_count;
748         sending_info->file_offset = 0;
749         sending_info->file_name_array = g_new0(char *, file_count + 1);
750
751         for (i = 0; i < file_count; i++) {
752                 sending_info->file_name_array[i] = g_strdup(file_name_array[i]);
753                 BT_DBG("file[%d]: %s", i, sending_info->file_name_array[i]);
754         }
755
756         _bt_opp_client_event_deinit();
757         _bt_opp_client_event_init();
758         //_bt_obex_client_started(agent_path);
759
760         BT_DBG("Adapter Status %d", _bt_adapter_get_status());
761         if (_bt_adapter_get_status() == BT_ACTIVATED) {
762                 BT_DBG("Going to call CreateSession");
763                 g_dbus_proxy_call(client_proxy, "CreateSession",
764                                                 g_variant_new("(sa{sv})", address, builder),
765                                                 G_DBUS_CALL_FLAGS_NONE,
766                                                 DBUS_TIEMOUT, NULL,
767                                                 (GAsyncReadyCallback)__bt_create_session_cb,
768                                                 NULL);
769         } else {
770                 GVariant *param = g_variant_new("(isi)", BLUETOOTH_ERROR_INTERNAL,
771                                 sending_info->address, sending_info->request_id);
772
773                 BT_DBG("Address[%s] RequestID[%d]", sending_info->address, sending_info->request_id);
774                 _bt_send_event(BT_OPP_CLIENT_EVENT, BLUETOOTH_EVENT_OPC_CONNECTED,
775                                                                         param);
776                 __bt_free_sending_info(sending_info);
777                 sending_info = NULL;
778         }
779         g_variant_builder_unref(builder);
780
781         BT_DBG("-");
782
783         return BLUETOOTH_ERROR_NONE;
784 }
785
786 int _bt_opp_client_push_files(int request_id, GDBusMethodInvocation *context,
787                                 bluetooth_device_address_t *remote_address,
788                                 char **file_path, int file_count)
789 {
790         BT_DBG("+");
791         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
792         bt_sending_data_t *data;
793
794         GVariant *out_param1 = NULL;
795
796         int result = BLUETOOTH_ERROR_NONE;
797         int i;
798
799         BT_CHECK_PARAMETER(remote_address, return);
800         BT_CHECK_PARAMETER(file_path, return);
801
802         /* Implement the queue */
803         _bt_convert_addr_type_to_string(address, remote_address->addr);
804
805         if (sending_info == NULL) {
806                 result = __bt_opp_client_start_sending(request_id,
807                                                 address, file_path, file_count);
808                 if (result != BLUETOOTH_ERROR_NONE)
809                         return result;
810         } else {
811                 /* Insert data in the queue */
812                 data = g_malloc0(sizeof(bt_sending_data_t));
813                 if (data == NULL)
814                         return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
815
816                 data->file_path = g_new0(char *, file_count + 1);
817                 data->address = g_strdup(address);
818                 data->file_count = file_count;
819                 data->request_id = request_id;
820
821                 for (i = 0; i < file_count; i++) {
822                         data->file_path[i] = g_strdup(file_path[i]);
823                         DBG_SECURE("file[%d]: %s", i, data->file_path[i]);
824                 }
825
826                 transfer_list = g_slist_append(transfer_list, data);
827         }
828
829         out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
830                                                         &request_id, sizeof(int),
831                                                         TRUE, NULL, NULL);
832
833
834         g_dbus_method_invocation_return_value(context,
835                         g_variant_new("(iv)", result, out_param1));
836
837         BT_DBG("-");
838
839         return result;
840 }
841
842 int _bt_opp_client_cancel_push(void)
843 {
844         BT_DBG("+");
845
846         GError *err = NULL;
847         int result = BLUETOOTH_ERROR_CANCEL_BY_USER;
848         GVariant *ret = NULL;
849         GVariant *param = NULL;
850         retv_if(sending_info == NULL, BLUETOOTH_ERROR_NOT_IN_OPERATION);
851
852         sending_info->is_canceled = TRUE;
853         sending_info->result = result;
854
855         if (sending_info->transfer_info) {
856
857                 ret = g_dbus_proxy_call_sync(sending_info->transfer_info->proxy,
858                                         "Cancel", NULL,
859                                         G_DBUS_CALL_FLAGS_NONE, -1,
860                                         NULL, &err);
861                 if (ret == NULL) {
862                         if (err != NULL) {
863                                 BT_ERR("Cancel Error: %s\n", err->message);
864                                 g_error_free(err);
865                         }
866                 } else {
867                         g_variant_unref(ret);
868                 }
869
870                 param = g_variant_new("(issti)", result,
871                                         sending_info->address,
872                                         sending_info->transfer_info->file_name,
873                                         sending_info->transfer_info->size,
874                                         sending_info->request_id);
875                 _bt_send_event(BT_OPP_CLIENT_EVENT,
876                                 BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE,
877                                 param);
878
879                 if (result == BLUETOOTH_ERROR_CANCEL_BY_USER) {
880                         BT_ERR("result is not BLUETOOTH_ERROR_NONE");
881                         __bt_sending_release();
882                         file_offset = 0;
883                 }
884
885         } else {
886                 g_idle_add(__bt_cancel_push_cb, NULL);
887         }
888
889         BT_DBG("-");
890
891         return BLUETOOTH_ERROR_NONE;
892 }
893
894 int _bt_opp_client_cancel_all_transfers(void)
895 {
896         BT_DBG("+");
897         if (transfer_list) {
898                 g_slist_free_full(transfer_list,
899                         (GDestroyNotify)__bt_free_sending_data);
900
901                 transfer_list = NULL;
902         }
903
904         _bt_opp_client_cancel_push();
905         BT_DBG("-");
906         return BLUETOOTH_ERROR_NONE;
907 }
908
909 int _bt_opp_client_is_sending(gboolean *sending)
910 {
911         BT_CHECK_PARAMETER(sending, return);
912
913         *sending = sending_info ? TRUE : FALSE;
914
915         return BLUETOOTH_ERROR_NONE;
916 }
917
918 void _bt_opp_client_check_pending_transfer(const char *address)
919 {
920         BT_DBG("+");
921
922         int result = BLUETOOTH_ERROR_CANCEL;
923         GVariant *param = NULL;
924         ret_if(sending_info == NULL);
925         ret_if(sending_info->transfer_info == NULL);
926
927         if (g_strcmp0(sending_info->address, address) == 0) {
928                 BT_INFO("Address Match.Cancel current transfer");
929                 sending_info->transfer_info->transfer_status = BT_TRANSFER_STATUS_COMPLETED;
930                 sending_info->result = result;
931
932                 if (!sending_info->is_canceled) {
933                         param = g_variant_new("(issti)", result,
934                                                 sending_info->address,
935                                                 sending_info->transfer_info->file_name,
936                                                 sending_info->transfer_info->size,
937                                                 sending_info->request_id);
938                         _bt_send_event(BT_OPP_CLIENT_EVENT,
939                                         BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE,
940                                         param);
941                         __bt_free_transfer_info(sending_info->transfer_info);
942                         sending_info->transfer_info = NULL;
943                         /* Reset the file offset as we will cancelled remaining files also */
944                         file_offset = 0;
945                 }
946                 param = g_variant_new("(isi)", sending_info->result,
947                                         sending_info->address,
948                                         sending_info->request_id);
949                 _bt_send_event(BT_OPP_CLIENT_EVENT,
950                                 BLUETOOTH_EVENT_OPC_DISCONNECTED,
951                                 param);
952
953                 __bt_sending_release();
954         }
955         BT_DBG("-");
956 }
957
958 int _bt_opp_get_client_progress(guint8 *progress)
959 {
960         if (sending_info == NULL || sending_info->transfer_info == NULL) {
961                 BT_ERR("No Active Outbound transfer");
962                 return BLUETOOTH_ERROR_NOT_FOUND;
963         }
964
965         *progress = (int)(((double)sending_info->transfer_info->progress /
966                         sending_info->transfer_info->size) * 100);
967
968         BT_DBG("Percentage: %d", *progress);
969         return BLUETOOTH_ERROR_NONE;
970 }
971
972 void _bt_cancel_queued_transfers(void)
973 {
974         bt_sending_data_t *data = NULL;
975         GVariant *param = NULL;
976
977         BT_INFO("Cancel queued Transfers:: Length of transfer list is %d",
978                                         g_slist_length(transfer_list));
979
980         while (transfer_list) {
981                 data = transfer_list->data;
982                 param = g_variant_new("(isi)", BLUETOOTH_ERROR_INTERNAL,
983                                 data->address, data->request_id);
984
985                 BT_DBG("Address[%s] RequestID[%d]", data->address, data->request_id);
986                 _bt_send_event(BT_OPP_CLIENT_EVENT, BLUETOOTH_EVENT_OPC_CONNECTED,
987                                                                         param);
988
989                 transfer_list = g_slist_remove(transfer_list, data);
990         }
991 }