2adf5e699798d43d934b1376bc99e7cf2109eba8
[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 <dbus/dbus-glib.h>
25 #include <dbus/dbus.h>
26 #include <glib.h>
27 #include <dlog.h>
28 #include <string.h>
29 #include <mime_type.h>
30
31 #include "bluetooth-api.h"
32 #include "bt-internal-types.h"
33
34 #include "bt-service-common.h"
35 #include "bt-service-event.h"
36 #include "bt-service-util.h"
37 #include "bt-service-opp-client.h"
38 #include "bt-service-obex-agent.h"
39
40 static GSList *transfer_list = NULL;
41
42 bt_sending_info_t *sending_info;
43 static int file_offset = 0;
44
45 static gboolean __bt_sending_release();
46 static void _bt_remove_session();
47
48 static int __bt_opp_client_start_sending(int request_id, char *address,
49                                         char **file_name_array, int file_count);
50
51 static GQuark __bt_opc_error_quark(void)
52 {
53         static GQuark quark = 0;
54         if (!quark)
55                 quark = g_quark_from_static_string("agent");
56
57         return quark;
58 }
59
60 static void __bt_free_transfer_info(bt_transfer_info_t *info)
61 {
62         ret_if(info == NULL);
63
64         if (info->proxy)
65                 g_object_unref(info->proxy);
66
67         if (info->properties_proxy)
68                 g_object_unref(info->properties_proxy);
69
70
71         g_free(info->transfer_name);
72         g_free(info->file_name);
73         g_free(info);
74 }
75
76 static void __bt_free_sending_info(bt_sending_info_t *info)
77 {
78         ret_if(info == NULL);
79
80         /* Free the sending variable */
81         __bt_free_transfer_info(info->transfer_info);
82
83         g_free(info->file_name_array);
84
85         g_free(info->address);
86         g_free(info);
87 }
88
89 static void __bt_value_free(GValue *value)
90 {
91         g_value_unset(value);
92         g_free(value);
93 }
94
95 static gboolean __bt_cancel_push_cb(gpointer data)
96 {
97         BT_DBG("+");
98
99         int result = BLUETOOTH_ERROR_CANCEL_BY_USER;
100
101         retv_if(sending_info == NULL, FALSE);
102         sending_info->result = result;
103
104         /* Send the event in only error none case */
105         _bt_send_event(BT_OPP_CLIENT_EVENT,
106                         BLUETOOTH_EVENT_OPC_CONNECTED,
107                         DBUS_TYPE_INT32, &result,
108                         DBUS_TYPE_STRING, &sending_info->address,
109                         DBUS_TYPE_INT32, &sending_info->request_id,
110                         DBUS_TYPE_INVALID);
111
112         __bt_free_sending_info(sending_info);
113         sending_info = NULL;
114
115         _bt_opp_client_event_deinit();
116
117         BT_DBG("Length of transfer list is %d", g_slist_length(transfer_list));
118
119          /*Operate remain works*/
120         if (g_slist_length(transfer_list) > 0) {
121                 bt_sending_data_t *node = NULL;
122
123                 node = transfer_list->data;
124                 if (node == NULL) {
125                         BT_ERR("data is NULL");
126                         return FALSE;
127                 }
128
129                 transfer_list = g_slist_remove(transfer_list, node);
130
131                 if (__bt_opp_client_start_sending(node->request_id,
132                                 node->address, node->file_path,
133                                 node->file_count) != BLUETOOTH_ERROR_NONE) {
134                         BT_ERR("Fail to start sending");
135                 }
136         }
137         BT_DBG("-");
138         return FALSE;
139 }
140
141 gboolean _bt_obex_client_progress(const char *transfer_path, int transferred)
142 {
143         BT_DBG("+");
144
145         int percentage_progress;
146         gint64 size;
147         int result = BLUETOOTH_ERROR_NONE;
148
149         retv_if(sending_info == NULL, TRUE);
150         retv_if(sending_info->transfer_info == NULL, TRUE);
151
152         if (g_strcmp0(sending_info->transfer_info->transfer_path,
153                         transfer_path) != 0) {
154                 BT_INFO("Path mismatch, previous transfer failed! Returning");
155                 return FALSE;
156         }
157
158         size = sending_info->transfer_info->size;
159
160         if (size != 0)
161                 percentage_progress = (int)(((gdouble)transferred /
162                                 (gdouble)size) * 100);
163         else
164                 percentage_progress = 0;
165
166         sending_info->transfer_info->transfer_status = BT_TRANSFER_STATUS_PROGRESS;
167         sending_info->result = result;
168
169         /* Send the event in only error none case */
170         _bt_send_event(BT_OPP_CLIENT_EVENT,
171                         BLUETOOTH_EVENT_OPC_TRANSFER_PROGRESS,
172                         DBUS_TYPE_INT32, &result,
173                         DBUS_TYPE_STRING, &sending_info->transfer_info->file_name,
174                         DBUS_TYPE_UINT64, &sending_info->transfer_info->size,
175                         DBUS_TYPE_INT32, &percentage_progress,
176                         DBUS_TYPE_INT32, &sending_info->request_id,
177                         DBUS_TYPE_INVALID);
178
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
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
200                                 : BLUETOOTH_ERROR_CANCEL;
201
202         sending_info->transfer_info->transfer_status = BT_TRANSFER_STATUS_COMPLETED;
203         sending_info->result = result;
204
205         if (!success) { /*In case of remote device reject, we need to send BLUETOOTH_EVENT_OPC_DISCONNECTED */
206                 BT_DBG("completed with error");
207                 if (!sending_info->is_canceled) {
208                         _bt_send_event(BT_OPP_CLIENT_EVENT,
209                                         BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE,
210                                         DBUS_TYPE_INT32, &result,
211                                         DBUS_TYPE_STRING, &sending_info->transfer_info->file_name,
212                                         DBUS_TYPE_UINT64, &sending_info->transfer_info->size,
213                                         DBUS_TYPE_INT32, &sending_info->request_id,
214                                         DBUS_TYPE_INVALID);
215
216                    __bt_free_transfer_info(sending_info->transfer_info);
217                    sending_info->transfer_info = NULL;
218                    /* Reset the file offset as we will cancelled remaining files also */
219                    file_offset = 0;
220                 }
221
222                 _bt_send_event(BT_OPP_CLIENT_EVENT,
223                                 BLUETOOTH_EVENT_OPC_DISCONNECTED,
224                                 DBUS_TYPE_INT32, &sending_info->result,
225                                 DBUS_TYPE_STRING, &sending_info->address,
226                                 DBUS_TYPE_INT32, &sending_info->request_id,
227                                 DBUS_TYPE_INVALID);
228
229                 __bt_sending_release();
230                 /* Sending info should not freed after sending_release it's
231                  * already freed in that API and if any pending request is
232                  * present then it recreate sending_info again.
233                  * And if we free it here then CreateSession method call will
234                  * made but RemoveSession method call will not done.
235                  */
236         } else {
237                 BT_DBG("complete success");
238                 /* Send the event in only error none case */
239                 _bt_send_event(BT_OPP_CLIENT_EVENT,
240                                 BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE,
241                                 DBUS_TYPE_INT32, &result,
242                                 DBUS_TYPE_STRING, &sending_info->transfer_info->file_name,
243                                 DBUS_TYPE_UINT64, &sending_info->transfer_info->size,
244                                 DBUS_TYPE_INT32, &sending_info->request_id,
245                                 DBUS_TYPE_INVALID);
246
247            __bt_free_transfer_info(sending_info->transfer_info);
248            sending_info->transfer_info = NULL;
249         }
250
251         BT_DBG("-");
252
253         return TRUE;
254 }
255
256 gboolean _bt_obex_client_started(const char *transfer_path)
257 {
258         GValue *value;
259         const char *transfer_name;
260         const char *file_name;
261         int size;
262         int result = BLUETOOTH_ERROR_NONE;
263         GHashTable *hash = NULL;
264         GError *error;
265         DBusGConnection *g_conn;
266         DBusGProxy *transfer_proxy;
267
268         if (sending_info == NULL || sending_info->is_canceled == TRUE) {
269                 result = BLUETOOTH_ERROR_CANCEL_BY_USER;
270                 goto canceled;
271         }
272
273         /* Get the session bus. */
274         g_conn = _bt_get_session_gconn();
275         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
276
277         __bt_free_transfer_info(sending_info->transfer_info);
278
279         sending_info->transfer_info = g_malloc0(sizeof(bt_transfer_info_t));
280
281         transfer_proxy = dbus_g_proxy_new_for_name(g_conn, BT_OBEXD_DBUS_NAME,
282                                 transfer_path, BT_PROPERTIES_INTERFACE);
283
284         retv_if(transfer_proxy == NULL, FALSE);
285
286         sending_info->transfer_info->proxy = transfer_proxy;
287
288         if (!dbus_g_proxy_call(transfer_proxy, "GetAll", NULL,
289                                 G_TYPE_STRING, BT_OBEX_TRANSFER_INTERFACE,
290                                 G_TYPE_INVALID,
291                                 dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
292                                 G_TYPE_VALUE), &hash, G_TYPE_INVALID))
293                 goto fail;
294
295         if (hash == NULL)
296                 goto fail;
297
298         value = g_hash_table_lookup(hash, "Name");
299         transfer_name = value ? g_value_get_string(value) : NULL;
300
301         value = g_hash_table_lookup(hash, "Filename");
302         file_name = value ? g_value_get_string(value) : NULL;
303
304         value = g_hash_table_lookup(hash, "Size");
305         size = value ? g_value_get_uint64(value) : 0;
306
307         sending_info->transfer_info->transfer_name = g_strdup(transfer_name);
308         sending_info->transfer_info->file_name = g_strdup(file_name);
309         sending_info->transfer_info->size = size;
310         sending_info->result = BLUETOOTH_ERROR_NONE;
311
312         g_hash_table_destroy(hash);
313
314         _bt_send_event(BT_OPP_CLIENT_EVENT,
315                         BLUETOOTH_EVENT_OPC_TRANSFER_STARTED,
316                         DBUS_TYPE_INT32, &result,
317                         DBUS_TYPE_STRING, &sending_info->transfer_info->file_name,
318                         DBUS_TYPE_UINT64, &sending_info->transfer_info->size,
319                         DBUS_TYPE_INT32, &sending_info->request_id,
320                         DBUS_TYPE_INVALID);
321
322         return TRUE;
323 canceled:
324         error = g_error_new(__bt_opc_error_quark(), BT_OBEX_AGENT_ERROR_CANCEL,
325                         "CancelledByUser");
326
327         g_error_free(error);
328
329         return FALSE;
330 fail:
331         result = BLUETOOTH_ERROR_INTERNAL;
332
333         /* Send the event in only error none case */
334         _bt_send_event(BT_OPP_CLIENT_EVENT,
335                         BLUETOOTH_EVENT_OPC_DISCONNECTED,
336                         DBUS_TYPE_INT32, &result,
337                         DBUS_TYPE_STRING, &sending_info->address,
338                         DBUS_TYPE_INT32, &sending_info->request_id,
339                         DBUS_TYPE_INVALID);
340
341         __bt_free_sending_info(sending_info);
342         sending_info = NULL;
343
344         _bt_opp_client_event_deinit();
345
346         return TRUE;
347 }
348
349 static void __bt_free_sending_data(gpointer data)
350 {
351         int i;
352         bt_sending_data_t *info = data;
353
354         ret_if(info == NULL);
355
356         for (i = 0; i < info->file_count; i++) {
357                 g_free(info->file_path[i]);
358         }
359
360         _bt_delete_request_id(info->request_id);
361
362         g_free(info->file_path);
363         g_free(info->address);
364         g_free(info);
365 }
366
367
368
369 static void __bt_sending_release_cb(DBusGProxy *proxy, DBusGProxyCall *call,
370                                         void *user_data)
371 {
372         BT_DBG("+");
373         ret_if(sending_info == NULL);
374
375         GError *error = NULL;
376         int result = BLUETOOTH_ERROR_NONE;
377
378         if (dbus_g_proxy_end_call(proxy, call, &error,
379                                                 G_TYPE_INVALID) == FALSE) {
380                 BT_ERR("%s", error->message);
381                 g_error_free(error);
382
383                 result = BLUETOOTH_ERROR_INTERNAL;
384         } else {
385                 file_offset = 0;
386                 BT_DBG("Session Removed");
387         }
388
389         sending_info->result = result;
390         /* Send the event in only error none case */
391         _bt_send_event(BT_OPP_CLIENT_EVENT,
392                         BLUETOOTH_EVENT_OPC_DISCONNECTED,
393                         DBUS_TYPE_INT32, &sending_info->result,
394                         DBUS_TYPE_STRING, &sending_info->address,
395                         DBUS_TYPE_INT32, &sending_info->request_id,
396                         DBUS_TYPE_INVALID);
397
398         __bt_free_sending_info(sending_info);
399         sending_info = NULL;
400
401         _bt_opp_client_event_deinit();
402
403         /* Operate remain works */
404         if (g_slist_length(transfer_list) > 0) {
405                 bt_sending_data_t *data = NULL;
406
407                 data = transfer_list->data;
408                 if (data == NULL)
409                         goto fail;
410
411                 transfer_list = g_slist_remove(transfer_list, data);
412
413                 BT_DBG("calling __bt_opp_client_start_sending");
414
415                 if (__bt_opp_client_start_sending(data->request_id,
416                                 data->address, data->file_path,
417                                 data->file_count) != BLUETOOTH_ERROR_NONE) {
418                         goto fail;
419                 }
420         }
421
422         return;
423 fail:
424         g_slist_free_full(transfer_list,
425                                 (GDestroyNotify)__bt_free_sending_data);
426         transfer_list = NULL;
427
428         BT_DBG("-");
429
430         return;
431 }
432
433 static void _bt_remove_session()
434 {
435         DBusGConnection *g_conn;
436         DBusGProxy *session_proxy;
437         DBusGProxyCall *proxy_call;
438
439         g_conn = _bt_get_session_gconn();
440         ret_if(g_conn == NULL);
441
442         session_proxy =  dbus_g_proxy_new_for_name(g_conn, BT_OBEXD_DBUS_NAME,
443                                                 BT_OBEX_CLIENT_PATH,
444                                                 BT_OBEX_CLIENT_INTERFACE);
445
446         ret_if(session_proxy == NULL);
447
448         proxy_call = dbus_g_proxy_begin_call(session_proxy, "RemoveSession",
449                 __bt_sending_release_cb, NULL, NULL,
450                 DBUS_TYPE_G_OBJECT_PATH, sending_info->session_path,
451                 G_TYPE_INVALID);
452         if (proxy_call == NULL) {
453                 BT_ERR("Fail to Remove session");
454                 g_object_unref(session_proxy);
455         }
456
457 }
458
459 static gboolean __bt_sending_release()
460 {
461         BT_DBG("+");
462
463         retv_if(sending_info == NULL, FALSE);
464
465         _bt_remove_session();
466         BT_DBG("-");
467         return TRUE;
468 }
469
470 void _bt_opc_disconnected(const char *session_path)
471 {
472         BT_DBG("+");
473
474         ret_if(sending_info == NULL);
475
476         if (g_strcmp0(sending_info->session_path,
477                         session_path) != 0) {
478                 BT_INFO("Path mismatch, previous transfer failed! Returning");
479                 return;
480         }
481
482         if (sending_info->transfer_info) {
483                 BT_INFO("sending_info is not NULL");
484                 if (sending_info->transfer_info->transfer_status == BT_TRANSFER_STATUS_PROGRESS ||
485                                 sending_info->transfer_info->transfer_status == BT_TRANSFER_STATUS_STARTED) {
486                         BT_INFO("Abnormal termination");
487
488                         _bt_send_event(BT_OPP_CLIENT_EVENT,
489                                         BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE,
490                                         DBUS_TYPE_INT32, &sending_info->result,
491                                         DBUS_TYPE_STRING, &sending_info->transfer_info->file_name,
492                                         DBUS_TYPE_UINT64, &sending_info->transfer_info->size,
493                                         DBUS_TYPE_INT32, &sending_info->request_id,
494                                         DBUS_TYPE_INVALID);
495                         __bt_free_transfer_info(sending_info->transfer_info);
496                 }
497         }
498
499         _bt_send_event(BT_OPP_CLIENT_EVENT,
500                         BLUETOOTH_EVENT_OPC_DISCONNECTED,
501                         DBUS_TYPE_INT32, &sending_info->result,
502                         DBUS_TYPE_STRING, &sending_info->address,
503                         DBUS_TYPE_INT32, &sending_info->request_id,
504                         DBUS_TYPE_INVALID);
505
506
507         __bt_free_sending_info(sending_info);
508         sending_info = NULL;
509
510         BT_DBG("-");
511 }
512
513 void _bt_sending_files(void)
514 {
515         BT_DBG("+");
516
517         DBusGConnection *g_conn;
518         DBusGProxy *client_proxy;
519         GError *err = NULL;
520         char *path = NULL;
521         GHashTable *hash = NULL;
522         GValue *value = NULL;
523         const char *transfer_name;
524         const char *file_name;
525         int size;
526         char *mimetype = NULL;
527         char *ext = NULL;
528
529
530         if (sending_info == NULL)
531                 return;
532
533         if (file_offset < sending_info->file_count){
534                 /* Get the session bus. */
535                 g_conn = _bt_get_session_gconn();
536                 ret_if(g_conn == NULL);
537
538                 client_proxy =  dbus_g_proxy_new_for_name(g_conn,
539                                                 BT_OBEXD_DBUS_NAME,
540                                                 sending_info->session_path,
541                                                 BT_OBEX_OBJECT_PUSH_INTERFACE);
542
543                 ret_if(client_proxy == NULL);
544
545                 BT_DBG("Calling SendFile");
546                 ext = strrchr(sending_info->file_name_array[file_offset], '.');
547
548                 if(!strcmp(ext+1, "imy"))
549                         mimetype = g_strdup("audio/imelody");
550
551                 if (!dbus_g_proxy_call(client_proxy, "SendFile", &err,
552                                 G_TYPE_STRING,
553                                 sending_info->file_name_array[file_offset],
554                                 G_TYPE_STRING, mimetype,
555                                 G_TYPE_INVALID, DBUS_TYPE_G_OBJECT_PATH, &path,
556                                 dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
557                                 &hash, G_TYPE_INVALID)) {
558                         if (err != NULL) {
559                                 BT_ERR("Calling SendFile failed: [%s]\n", err->message);
560                                 g_error_free(err);
561                         }
562                         g_free(mimetype);
563                         return;
564                 }
565
566                 g_free(mimetype);
567
568                 if (hash == NULL)
569                         return;
570
571                 __bt_free_transfer_info(sending_info->transfer_info);
572
573                 sending_info->transfer_info = g_malloc0(sizeof(bt_transfer_info_t));
574
575                 value = g_hash_table_lookup(hash, "Name");
576                 transfer_name = value ? g_value_get_string(value) : NULL;
577
578                 value = g_hash_table_lookup(hash, "Filename");
579                 file_name = value ? g_value_get_string(value) : NULL;
580
581                 value = g_hash_table_lookup(hash, "Size");
582                 size = value ? g_value_get_uint64(value) : 0;
583
584                 sending_info->transfer_info->transfer_name = g_strdup(transfer_name);
585                 sending_info->transfer_info->file_name = g_strdup(file_name);
586                 sending_info->transfer_info->size = size;
587                 sending_info->transfer_info->transfer_path = path;
588                 sending_info->transfer_info->transfer_status = BT_TRANSFER_STATUS_QUEUED;
589                 sending_info->result = BLUETOOTH_ERROR_NONE;
590
591                 g_hash_table_destroy(hash);
592
593                 file_offset++;
594         }else{
595                 file_offset = 0;
596                 __bt_sending_release();
597         }
598
599         BT_DBG("-");
600 }
601
602 static void __bt_create_session_cb(DBusGProxy *proxy, DBusGProxyCall *call,
603                                         void *user_data)
604 {
605         BT_DBG("+");
606
607         GError *error = NULL;
608         int result = BLUETOOTH_ERROR_NONE;
609         char *session_path = NULL;
610
611         if (dbus_g_proxy_end_call(proxy, call, &error,
612                 DBUS_TYPE_G_OBJECT_PATH, &session_path, G_TYPE_INVALID) == FALSE) {
613
614                 BT_ERR("%s", error->message);
615                 g_error_free(error);
616
617                 result = BLUETOOTH_ERROR_INTERNAL;
618         }else{
619                 BT_DBG("Session created");
620                 if(sending_info != NULL)
621                         sending_info->session_path = g_strdup(session_path);
622 }
623         g_free(session_path);
624         g_object_unref(proxy);
625         ret_if(sending_info == NULL);
626
627         sending_info->sending_proxy = NULL;
628         sending_info->result = result;
629
630         /* Send the event in only error none case */
631         _bt_send_event(BT_OPP_CLIENT_EVENT,
632                         BLUETOOTH_EVENT_OPC_CONNECTED,
633                         DBUS_TYPE_INT32, &result,
634                         DBUS_TYPE_STRING, &sending_info->address,
635                         DBUS_TYPE_INT32, &sending_info->request_id,
636                         DBUS_TYPE_INVALID);
637
638         if (result != BLUETOOTH_ERROR_NONE) {
639                 BT_ERR("Calling __bt_sending_release");
640                 __bt_sending_release();
641
642                 __bt_free_sending_info(sending_info);
643                 sending_info = NULL;
644         }else {
645                 BT_DBG("Calling sending_files");
646                 _bt_sending_files();
647         }
648         BT_DBG("-");
649
650 }
651
652 static int __bt_opp_client_start_sending(int request_id, char *address,
653                                         char **file_name_array, int file_count)
654 {
655         BT_DBG("+");
656
657         GHashTable *hash;
658         GValue *value;
659         DBusGConnection *g_conn;
660         DBusGProxy *client_proxy;
661         DBusGProxyCall *proxy_call;
662
663         int i;
664
665         BT_CHECK_PARAMETER(address, return);
666         BT_CHECK_PARAMETER(file_name_array, return);
667
668         /* Get the session bus. */
669         g_conn = _bt_get_session_gconn();
670         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
671
672         client_proxy =  dbus_g_proxy_new_for_name(g_conn, BT_OBEX_SERVICE_NAME,
673                                         BT_OBEX_CLIENT_PATH, BT_OBEX_CLIENT_INTERFACE);
674
675         retv_if(client_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
676
677         BT_DBG("client_proxy is not NULL");
678
679         hash = g_hash_table_new_full(g_str_hash, g_str_equal,
680                                      NULL, (GDestroyNotify)__bt_value_free);
681
682         value = g_new0(GValue, 1);
683         g_value_init(value, G_TYPE_STRING);
684
685         g_value_set_string(value, "OPP");
686         g_hash_table_insert(hash, "Target", value);
687         BT_DBG("Hash Table success");
688
689         __bt_free_sending_info(sending_info);
690
691         sending_info = g_malloc0(sizeof(bt_sending_info_t));
692         sending_info->address = g_strdup(address);
693         sending_info->request_id = request_id;
694
695         sending_info->file_count = file_count;
696         sending_info->file_offset = 0;
697         sending_info->file_name_array = g_new0(char *, file_count + 1);
698
699         for (i = 0; i < file_count; i++) {
700                 sending_info->file_name_array[i] = g_strdup(file_name_array[i]);
701                 BT_DBG("file[%d]: %s", i, sending_info->file_name_array[i]);
702         }
703
704         _bt_opp_client_event_deinit();
705         _bt_opp_client_event_init();
706         //_bt_obex_client_started(agent_path);
707
708         BT_DBG("Going to call CreateSession");
709
710         proxy_call = dbus_g_proxy_begin_call(client_proxy, "CreateSession",
711                         __bt_create_session_cb, NULL, NULL,
712                         G_TYPE_STRING, address,
713                         dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
714                         hash, G_TYPE_INVALID);
715
716         if (proxy_call == NULL) {
717                         BT_ERR("Fail to Send files");
718                         g_hash_table_destroy(hash);
719                         g_object_unref(client_proxy);
720                         __bt_free_sending_info(sending_info);
721                         _bt_opp_client_event_deinit();
722                         sending_info = NULL;
723                         return BLUETOOTH_ERROR_INTERNAL;
724         }
725
726         BT_DBG("After CreateSession");
727
728         sending_info->sending_proxy = proxy_call;
729         g_hash_table_destroy(hash);
730
731         BT_DBG("-");
732
733         return BLUETOOTH_ERROR_NONE;
734 }
735
736
737 int _bt_opp_client_push_files(int request_id, DBusGMethodInvocation *context,
738                                 bluetooth_device_address_t *remote_address,
739                                 char **file_path, int file_count)
740 {
741         BT_DBG("+");
742         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
743         bt_sending_data_t *data;
744
745         GArray *out_param1 = NULL;
746         GArray *out_param2 = NULL;
747
748         int result = BLUETOOTH_ERROR_NONE;
749         int i;
750
751         BT_CHECK_PARAMETER(remote_address, return);
752         BT_CHECK_PARAMETER(file_path, return);
753
754         /* Implement the queue */
755         _bt_convert_addr_type_to_string(address, remote_address->addr);
756
757         if (sending_info == NULL) {
758                 result = __bt_opp_client_start_sending(request_id,
759                                                 address, file_path, file_count);
760                 if (result != BLUETOOTH_ERROR_NONE)
761                         return result;
762         } else {
763                 /* Insert data in the queue */
764                 data = g_malloc0(sizeof(bt_sending_data_t));
765                 data->file_path = g_new0(char *, file_count + 1);
766                 data->address = g_strdup(address);
767                 data->file_count = file_count;
768                 data->request_id = request_id;
769
770                 for (i = 0; i < file_count; i++) {
771                         data->file_path[i] = g_strdup(file_path[i]);
772                         DBG_SECURE("file[%d]: %s", i, data->file_path[i]);
773                 }
774
775                 transfer_list = g_slist_append(transfer_list, data);
776         }
777
778         out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
779         out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar));
780
781         g_array_append_vals(out_param1, &request_id,
782                                 sizeof(int));
783         g_array_append_vals(out_param2, &result, sizeof(int));
784
785         dbus_g_method_return(context, out_param1, out_param2);
786
787         g_array_free(out_param1, TRUE);
788         g_array_free(out_param2, TRUE);
789
790         BT_DBG("-");
791
792         return result;
793 }
794
795 int _bt_opp_client_cancel_push(void)
796 {
797         BT_DBG("+");
798
799         DBusGConnection *g_conn;
800         DBusGProxy *client_proxy;
801         int result = BLUETOOTH_ERROR_CANCEL_BY_USER;
802
803         retv_if(sending_info == NULL, BLUETOOTH_ERROR_NOT_IN_OPERATION);
804
805         sending_info->is_canceled = TRUE;
806         sending_info->result = result;
807
808         if (sending_info->transfer_info) {
809                 BT_DBG("calling cancel in Bluez");
810                 dbus_g_proxy_call_no_reply(sending_info->transfer_info->proxy,
811                                         "Cancel", G_TYPE_INVALID,
812                                         G_TYPE_INVALID);
813
814                 _bt_send_event(BT_OPP_CLIENT_EVENT,
815                                 BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE,
816                                 DBUS_TYPE_INT32, &result,
817                                 DBUS_TYPE_STRING, &sending_info->transfer_info->file_name,
818                                 DBUS_TYPE_UINT64, &sending_info->transfer_info->size,
819                                 DBUS_TYPE_INT32, &sending_info->request_id,
820                                 DBUS_TYPE_INVALID);
821
822                 if (result == BLUETOOTH_ERROR_CANCEL_BY_USER) {
823                         BT_ERR("result is not BLUETOOTH_ERROR_NONE");
824                         __bt_sending_release();
825                         file_offset = 0;
826                 }
827         } else {
828                 retv_if(sending_info->sending_proxy == NULL,
829                                         BLUETOOTH_ERROR_INTERNAL);
830
831                 g_conn = _bt_get_session_gconn();
832                 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
833
834                 client_proxy =  dbus_g_proxy_new_for_name(g_conn, BT_OBEX_SERVICE_NAME,
835                                                 BT_OBEX_CLIENT_PATH, BT_OBEX_CLIENT_INTERFACE);
836                 retv_if(client_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
837
838                 dbus_g_proxy_cancel_call(client_proxy,
839                                         sending_info->sending_proxy);
840
841                 g_idle_add(__bt_cancel_push_cb, NULL);
842         }
843
844         BT_DBG("-");
845
846         return BLUETOOTH_ERROR_NONE;
847 }
848
849 int _bt_opp_client_cancel_all_transfers(void)
850 {
851         BT_DBG("+");
852         if (transfer_list) {
853                 g_slist_free_full(transfer_list,
854                         (GDestroyNotify)__bt_free_sending_data);
855
856                 transfer_list = NULL;
857         }
858
859         _bt_opp_client_cancel_push();
860         BT_DBG("-");
861         return BLUETOOTH_ERROR_NONE;
862 }
863
864 int _bt_opp_client_is_sending(gboolean *sending)
865 {
866         BT_CHECK_PARAMETER(sending, return);
867
868         *sending = sending_info ? TRUE : FALSE;
869
870         return BLUETOOTH_ERROR_NONE;
871 }
872
873 void _bt_opp_client_check_pending_transfer(const char *address)
874 {
875         BT_DBG("+");
876
877         int result = BLUETOOTH_ERROR_CANCEL;
878
879         ret_if(sending_info == NULL);
880         ret_if(sending_info->transfer_info == NULL);
881
882         if (g_strcmp0(sending_info->address, address) == 0) {
883                 BT_INFO("Address Match.Cancel current transfer");
884                 sending_info->transfer_info->transfer_status = BT_TRANSFER_STATUS_COMPLETED;
885                 sending_info->result = result;
886
887                 if (!sending_info->is_canceled) {
888                         _bt_send_event(BT_OPP_CLIENT_EVENT,
889                                         BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE,
890                                         DBUS_TYPE_INT32, &result,
891                                         DBUS_TYPE_STRING, &sending_info->transfer_info->file_name,
892                                         DBUS_TYPE_UINT64, &sending_info->transfer_info->size,
893                                         DBUS_TYPE_INT32, &sending_info->request_id,
894                                         DBUS_TYPE_INVALID);
895
896                         __bt_free_transfer_info(sending_info->transfer_info);
897                         sending_info->transfer_info = NULL;
898                         /* Reset the file offset as we will cancelled remaining files also */
899                         file_offset = 0;
900                 }
901
902                 _bt_send_event(BT_OPP_CLIENT_EVENT,
903                                 BLUETOOTH_EVENT_OPC_DISCONNECTED,
904                                 DBUS_TYPE_INT32, &sending_info->result,
905                                 DBUS_TYPE_STRING, &sending_info->address,
906                                 DBUS_TYPE_INT32, &sending_info->request_id,
907                                 DBUS_TYPE_INVALID);
908
909                 __bt_sending_release();
910         }
911         BT_DBG("-");
912 }