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