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