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