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