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