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