Code Sync [Tizen3.0]: Merged the tizen_2.4 Spin code to tizen.org
[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 : 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                         _bt_send_event(BT_OPP_CLIENT_EVENT,
208                                         BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE,
209                                         DBUS_TYPE_INT32, &result,
210                                         DBUS_TYPE_STRING, &sending_info->transfer_info->file_name,
211                                         DBUS_TYPE_UINT64, &sending_info->transfer_info->size,
212                                         DBUS_TYPE_INT32, &sending_info->request_id,
213                                         DBUS_TYPE_INVALID);
214
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
221                 _bt_send_event(BT_OPP_CLIENT_EVENT,
222                                 BLUETOOTH_EVENT_OPC_DISCONNECTED,
223                                 DBUS_TYPE_INT32, &sending_info->result,
224                                 DBUS_TYPE_STRING, &sending_info->address,
225                                 DBUS_TYPE_INT32, &sending_info->request_id,
226                                 DBUS_TYPE_INVALID);
227
228                 __bt_sending_release();
229                 /* Sending info should not freed after sending_release it's
230                  * already freed in that API and if any pending request is
231                  * present then it recreate sending_info again.
232                  * And if we free it here then CreateSession method call will
233                  * made but RemoveSession method call will not done.
234                  */
235         } else {
236                 BT_DBG("complete success");
237                 /* Send the event in only error none case */
238                 _bt_send_event(BT_OPP_CLIENT_EVENT,
239                                 BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE,
240                                 DBUS_TYPE_INT32, &result,
241                                 DBUS_TYPE_STRING, &sending_info->transfer_info->file_name,
242                                 DBUS_TYPE_UINT64, &sending_info->transfer_info->size,
243                                 DBUS_TYPE_INT32, &sending_info->request_id,
244                                 DBUS_TYPE_INVALID);
245
246            __bt_free_transfer_info(sending_info->transfer_info);
247            sending_info->transfer_info = NULL;
248         }
249
250         BT_DBG("-");
251
252         return TRUE;
253 }
254
255 gboolean _bt_obex_client_started(const char *transfer_path)
256 {
257         BT_DBG("+");
258
259         int result = BLUETOOTH_ERROR_NONE;
260         GError *error;
261         DBusGConnection *g_conn;
262         DBusGProxy *properties_proxy;
263         DBusGProxy *transfer_proxy;
264
265         if (sending_info == NULL || sending_info->is_canceled == TRUE) {
266                 result = BLUETOOTH_ERROR_CANCEL_BY_USER;
267                 goto canceled;
268         }
269
270         /* Get the session bus. */
271         g_conn = _bt_get_session_gconn();
272         retv_if(g_conn == NULL, FALSE);
273
274         properties_proxy = dbus_g_proxy_new_for_name(g_conn, BT_OBEXD_DBUS_NAME,
275                         transfer_path, BT_PROPERTIES_INTERFACE);
276
277         retv_if(properties_proxy == NULL, FALSE);
278
279         sending_info->transfer_info->properties_proxy = properties_proxy;
280
281         transfer_proxy = dbus_g_proxy_new_for_name(g_conn, BT_OBEXD_DBUS_NAME,
282                         transfer_path, BT_OBEX_TRANSFER_INTERFACE);
283
284         retv_if(transfer_proxy == NULL, FALSE);
285
286         sending_info->transfer_info->proxy = transfer_proxy;
287
288         sending_info->transfer_info->transfer_status = BT_TRANSFER_STATUS_STARTED;
289         sending_info->result = result;
290
291         _bt_send_event(BT_OPP_CLIENT_EVENT,
292                         BLUETOOTH_EVENT_OPC_TRANSFER_STARTED,
293                         DBUS_TYPE_INT32, &result,
294                         DBUS_TYPE_STRING, &sending_info->transfer_info->file_name,
295                         DBUS_TYPE_UINT64, &sending_info->transfer_info->size,
296                         DBUS_TYPE_INT32, &sending_info->request_id,
297                         DBUS_TYPE_INVALID);
298
299         BT_DBG("-");
300         return TRUE;
301 canceled:
302         error = g_error_new(__bt_opc_error_quark(), BT_OBEX_AGENT_ERROR_CANCEL,
303                         "CancelledByUser");
304
305         g_error_free(error);
306
307         BT_DBG("-");
308         return FALSE;
309 }
310
311 static void __bt_free_sending_data(gpointer data)
312 {
313         int i;
314         bt_sending_data_t *info = data;
315
316         ret_if(info == NULL);
317
318         for (i = 0; i < info->file_count; i++) {
319                 g_free(info->file_path[i]);
320         }
321
322         _bt_delete_request_id(info->request_id);
323
324         g_free(info->file_path);
325         g_free(info->address);
326         g_free(info);
327 }
328
329 static void __bt_sending_release_cb(DBusGProxy *proxy, DBusGProxyCall *call,
330                                         void *user_data)
331 {
332         BT_DBG("+");
333         ret_if(sending_info == NULL);
334
335         GError *error = NULL;
336         int result = BLUETOOTH_ERROR_NONE;
337
338         if (dbus_g_proxy_end_call(proxy, call, &error,
339                                                 G_TYPE_INVALID) == FALSE) {
340                 BT_ERR("%s", error->message);
341                 g_error_free(error);
342
343                 result = BLUETOOTH_ERROR_INTERNAL;
344         } else {
345                 file_offset = 0;
346                 BT_DBG("Session Removed");
347         }
348
349         sending_info->result = result;
350         /* Send the event in only error none case */
351         _bt_send_event(BT_OPP_CLIENT_EVENT,
352                         BLUETOOTH_EVENT_OPC_DISCONNECTED,
353                         DBUS_TYPE_INT32, &sending_info->result,
354                         DBUS_TYPE_STRING, &sending_info->address,
355                         DBUS_TYPE_INT32, &sending_info->request_id,
356                         DBUS_TYPE_INVALID);
357
358         __bt_free_sending_info(sending_info);
359         sending_info = NULL;
360
361         _bt_opp_client_event_deinit();
362
363         /* Operate remain works */
364         if (g_slist_length(transfer_list) > 0) {
365                 bt_sending_data_t *data = NULL;
366
367                 data = transfer_list->data;
368                 if (data == NULL)
369                         goto fail;
370
371                 transfer_list = g_slist_remove(transfer_list, data);
372
373                 BT_DBG("calling __bt_opp_client_start_sending");
374
375                 if (__bt_opp_client_start_sending(data->request_id,
376                                 data->address, data->file_path,
377                                 data->file_count) != BLUETOOTH_ERROR_NONE) {
378                         goto fail;
379                 }
380         }
381
382         return;
383 fail:
384         g_slist_free_full(transfer_list,
385                                 (GDestroyNotify)__bt_free_sending_data);
386         transfer_list = NULL;
387
388         BT_DBG("-");
389
390         return;
391 }
392
393 static void _bt_remove_session()
394 {
395         DBusGConnection *g_conn;
396         DBusGProxy *session_proxy;
397         DBusGProxyCall *proxy_call;
398
399         g_conn = _bt_get_session_gconn();
400         ret_if(g_conn == NULL);
401
402         session_proxy =  dbus_g_proxy_new_for_name(g_conn, BT_OBEXD_DBUS_NAME,
403                                                 BT_OBEX_CLIENT_PATH,
404                                                 BT_OBEX_CLIENT_INTERFACE);
405
406         ret_if(session_proxy == NULL);
407
408         proxy_call = dbus_g_proxy_begin_call(session_proxy, "RemoveSession",
409                 __bt_sending_release_cb, NULL, NULL,
410                 DBUS_TYPE_G_OBJECT_PATH, sending_info->session_path,
411                 G_TYPE_INVALID);
412         if (proxy_call == NULL) {
413                 BT_ERR("Fail to Remove session");
414                 g_object_unref(session_proxy);
415         }
416
417 }
418
419 static gboolean __bt_sending_release()
420 {
421         BT_DBG("+");
422
423         retv_if(sending_info == NULL, FALSE);
424
425         _bt_remove_session();
426         BT_DBG("-");
427         return TRUE;
428 }
429
430 void _bt_opc_disconnected(const char *session_path)
431 {
432         BT_DBG("+");
433
434         ret_if(sending_info == NULL);
435
436         if (g_strcmp0(sending_info->session_path,
437                         session_path) != 0) {
438                 BT_INFO("Path mismatch, previous transfer failed! Returning");
439                 return;
440         }
441
442         if (sending_info->transfer_info) {
443                 BT_INFO("sending_info is not NULL");
444                 if (sending_info->transfer_info->transfer_status == BT_TRANSFER_STATUS_PROGRESS ||
445                                 sending_info->transfer_info->transfer_status == BT_TRANSFER_STATUS_STARTED) {
446                         BT_INFO("Abnormal termination");
447
448                         _bt_send_event(BT_OPP_CLIENT_EVENT,
449                                         BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE,
450                                         DBUS_TYPE_INT32, &sending_info->result,
451                                         DBUS_TYPE_STRING, &sending_info->transfer_info->file_name,
452                                         DBUS_TYPE_UINT64, &sending_info->transfer_info->size,
453                                         DBUS_TYPE_INT32, &sending_info->request_id,
454                                         DBUS_TYPE_INVALID);
455                         __bt_free_transfer_info(sending_info->transfer_info);
456                 }
457         }
458
459         _bt_send_event(BT_OPP_CLIENT_EVENT,
460                         BLUETOOTH_EVENT_OPC_DISCONNECTED,
461                         DBUS_TYPE_INT32, &sending_info->result,
462                         DBUS_TYPE_STRING, &sending_info->address,
463                         DBUS_TYPE_INT32, &sending_info->request_id,
464                         DBUS_TYPE_INVALID);
465
466
467         __bt_free_sending_info(sending_info);
468         sending_info = NULL;
469
470         BT_DBG("-");
471 }
472
473 void _bt_sending_files(void)
474 {
475         BT_DBG("+");
476
477         DBusGConnection *g_conn;
478         DBusGProxy *client_proxy;
479         GError *err = NULL;
480         char *path = NULL;
481         GHashTable *hash = NULL;
482         GValue *value = NULL;
483         const char *transfer_name;
484         const char *file_name;
485         int size;
486         char *mimetype = NULL;
487         char *ext = NULL;
488
489
490         if (sending_info == NULL)
491                 return;
492
493         if (file_offset < sending_info->file_count){
494                 /* Get the session bus. */
495                 g_conn = _bt_get_session_gconn();
496                 ret_if(g_conn == NULL);
497
498                 client_proxy =  dbus_g_proxy_new_for_name(g_conn,
499                                                 BT_OBEXD_DBUS_NAME,
500                                                 sending_info->session_path,
501                                                 BT_OBEX_OBJECT_PUSH_INTERFACE);
502
503                 ret_if(client_proxy == NULL);
504
505                 BT_DBG("Calling SendFile");
506                 ext = strrchr(sending_info->file_name_array[file_offset], '.');
507
508                 if(!strcmp(ext+1, "imy"))
509                         mimetype = g_strdup("audio/imelody");
510
511                 if (!dbus_g_proxy_call(client_proxy, "SendFile", &err,
512                                 G_TYPE_STRING,
513                                 sending_info->file_name_array[file_offset],
514                                 G_TYPE_STRING, mimetype,
515                                 G_TYPE_INVALID, DBUS_TYPE_G_OBJECT_PATH, &path,
516                                 dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
517                                 &hash, G_TYPE_INVALID)) {
518                         if (err != NULL) {
519                                 BT_ERR("Calling SendFile failed: [%s]\n", err->message);
520                                 g_error_free(err);
521                         }
522                         g_free(mimetype);
523                         return;
524                 }
525
526                 g_free(mimetype);
527
528                 if (hash == NULL)
529                         return;
530
531                 __bt_free_transfer_info(sending_info->transfer_info);
532
533                 sending_info->transfer_info = g_malloc0(sizeof(bt_transfer_info_t));
534
535                 value = g_hash_table_lookup(hash, "Name");
536                 transfer_name = value ? g_value_get_string(value) : NULL;
537
538                 value = g_hash_table_lookup(hash, "Filename");
539                 file_name = value ? g_value_get_string(value) : NULL;
540
541                 value = g_hash_table_lookup(hash, "Size");
542                 size = value ? g_value_get_uint64(value) : 0;
543
544                 sending_info->transfer_info->transfer_name = g_strdup(transfer_name);
545                 sending_info->transfer_info->file_name = g_strdup(file_name);
546                 sending_info->transfer_info->size = size;
547                 sending_info->transfer_info->transfer_path = path;
548                 sending_info->transfer_info->transfer_status = BT_TRANSFER_STATUS_QUEUED;
549                 sending_info->result = BLUETOOTH_ERROR_NONE;
550
551                 g_hash_table_destroy(hash);
552
553                 file_offset++;
554         }else{
555                 file_offset = 0;
556                 __bt_sending_release();
557         }
558
559         BT_DBG("-");
560 }
561
562 static void __bt_create_session_cb(DBusGProxy *proxy, DBusGProxyCall *call,
563                                         void *user_data)
564 {
565         BT_DBG("+");
566
567         GError *error = NULL;
568         int result = BLUETOOTH_ERROR_NONE;
569         char *session_path = NULL;
570
571         if (dbus_g_proxy_end_call(proxy, call, &error,
572                 DBUS_TYPE_G_OBJECT_PATH, &session_path, G_TYPE_INVALID) == FALSE) {
573
574                 BT_ERR("%s", error->message);
575                 g_error_free(error);
576
577                 result = BLUETOOTH_ERROR_INTERNAL;
578         }else{
579                 BT_DBG("Session created");
580                 if(sending_info != NULL)
581                         sending_info->session_path = g_strdup(session_path);
582 }
583         g_free(session_path);
584         g_object_unref(proxy);
585         ret_if(sending_info == NULL);
586
587         sending_info->sending_proxy = NULL;
588         sending_info->result = result;
589
590         /* Send the event in only error none case */
591         _bt_send_event(BT_OPP_CLIENT_EVENT,
592                         BLUETOOTH_EVENT_OPC_CONNECTED,
593                         DBUS_TYPE_INT32, &result,
594                         DBUS_TYPE_STRING, &sending_info->address,
595                         DBUS_TYPE_INT32, &sending_info->request_id,
596                         DBUS_TYPE_INVALID);
597
598         if (result != BLUETOOTH_ERROR_NONE) {
599                 BT_ERR("Calling __bt_sending_release");
600                 __bt_sending_release();
601
602                 __bt_free_sending_info(sending_info);
603                 sending_info = NULL;
604         }else {
605                 BT_DBG("Calling sending_files");
606                 _bt_sending_files();
607         }
608         BT_DBG("-");
609
610 }
611
612 static int __bt_opp_client_start_sending(int request_id, char *address,
613                                         char **file_name_array, int file_count)
614 {
615         BT_DBG("+");
616
617         GHashTable *hash;
618         GValue *value;
619         DBusGConnection *g_conn;
620         DBusGProxy *client_proxy;
621         DBusGProxyCall *proxy_call;
622
623         int i;
624
625         BT_CHECK_PARAMETER(address, return);
626         BT_CHECK_PARAMETER(file_name_array, return);
627
628         /* Get the session bus. */
629         g_conn = _bt_get_session_gconn();
630         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
631
632         client_proxy =  dbus_g_proxy_new_for_name(g_conn, BT_OBEX_SERVICE_NAME,
633                                         BT_OBEX_CLIENT_PATH, BT_OBEX_CLIENT_INTERFACE);
634
635         retv_if(client_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
636
637         BT_DBG("client_proxy is not NULL");
638
639         hash = g_hash_table_new_full(g_str_hash, g_str_equal,
640                                      NULL, (GDestroyNotify)__bt_value_free);
641
642         value = g_new0(GValue, 1);
643         g_value_init(value, G_TYPE_STRING);
644
645         g_value_set_string(value, "OPP");
646         g_hash_table_insert(hash, "Target", value);
647         BT_DBG("Hash Table success");
648
649         __bt_free_sending_info(sending_info);
650
651         sending_info = g_malloc0(sizeof(bt_sending_info_t));
652         sending_info->address = g_strdup(address);
653         sending_info->request_id = request_id;
654
655         sending_info->file_count = file_count;
656         sending_info->file_offset = 0;
657         sending_info->file_name_array = g_new0(char *, file_count + 1);
658
659         for (i = 0; i < file_count; i++) {
660                 sending_info->file_name_array[i] = g_strdup(file_name_array[i]);
661                 BT_DBG("file[%d]: %s", i, sending_info->file_name_array[i]);
662         }
663
664         _bt_opp_client_event_deinit();
665         _bt_opp_client_event_init();
666         //_bt_obex_client_started(agent_path);
667
668         BT_DBG("Going to call CreateSession");
669
670         proxy_call = dbus_g_proxy_begin_call(client_proxy, "CreateSession",
671                         __bt_create_session_cb, NULL, NULL,
672                         G_TYPE_STRING, address,
673                         dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
674                         hash, G_TYPE_INVALID);
675
676         if (proxy_call == NULL) {
677                         BT_ERR("Fail to Send files");
678                         g_hash_table_destroy(hash);
679                         g_object_unref(client_proxy);
680                         __bt_free_sending_info(sending_info);
681                         _bt_opp_client_event_deinit();
682                         sending_info = NULL;
683                         return BLUETOOTH_ERROR_INTERNAL;
684         }
685
686         BT_DBG("After CreateSession");
687
688         sending_info->sending_proxy = proxy_call;
689         g_hash_table_destroy(hash);
690
691         BT_DBG("-");
692
693         return BLUETOOTH_ERROR_NONE;
694 }
695
696
697 int _bt_opp_client_push_files(int request_id, DBusGMethodInvocation *context,
698                                 bluetooth_device_address_t *remote_address,
699                                 char **file_path, int file_count)
700 {
701         BT_DBG("+");
702         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
703         bt_sending_data_t *data;
704
705         GArray *out_param1 = NULL;
706         GArray *out_param2 = NULL;
707
708         int result = BLUETOOTH_ERROR_NONE;
709         int i;
710
711         BT_CHECK_PARAMETER(remote_address, return);
712         BT_CHECK_PARAMETER(file_path, return);
713
714         /* Implement the queue */
715         _bt_convert_addr_type_to_string(address, remote_address->addr);
716
717         if (sending_info == NULL) {
718                 result = __bt_opp_client_start_sending(request_id,
719                                                 address, file_path, file_count);
720                 if (result != BLUETOOTH_ERROR_NONE)
721                         return result;
722         } else {
723                 /* Insert data in the queue */
724                 data = g_malloc0(sizeof(bt_sending_data_t));
725                 data->file_path = g_new0(char *, file_count + 1);
726                 data->address = g_strdup(address);
727                 data->file_count = file_count;
728                 data->request_id = request_id;
729
730                 for (i = 0; i < file_count; i++) {
731                         data->file_path[i] = g_strdup(file_path[i]);
732                         DBG_SECURE("file[%d]: %s", i, data->file_path[i]);
733                 }
734
735                 transfer_list = g_slist_append(transfer_list, data);
736         }
737
738         out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
739         out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar));
740
741         g_array_append_vals(out_param1, &request_id,
742                                 sizeof(int));
743         g_array_append_vals(out_param2, &result, sizeof(int));
744
745         dbus_g_method_return(context, out_param1, out_param2);
746
747         g_array_free(out_param1, TRUE);
748         g_array_free(out_param2, TRUE);
749
750         BT_DBG("-");
751
752         return result;
753 }
754
755 int _bt_opp_client_cancel_push(void)
756 {
757         BT_DBG("+");
758
759         DBusGConnection *g_conn;
760         DBusGProxy *client_proxy;
761         int result = BLUETOOTH_ERROR_CANCEL_BY_USER;
762
763         retv_if(sending_info == NULL, BLUETOOTH_ERROR_NOT_IN_OPERATION);
764
765         sending_info->is_canceled = TRUE;
766         sending_info->result = result;
767
768         if (sending_info->transfer_info) {
769                 BT_DBG("calling cancel in Bluez");
770                 dbus_g_proxy_call_no_reply(sending_info->transfer_info->proxy,
771                                         "Cancel", G_TYPE_INVALID,
772                                         G_TYPE_INVALID);
773
774                 _bt_send_event(BT_OPP_CLIENT_EVENT,
775                                 BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE,
776                                 DBUS_TYPE_INT32, &result,
777                                 DBUS_TYPE_STRING, &sending_info->transfer_info->file_name,
778                                 DBUS_TYPE_UINT64, &sending_info->transfer_info->size,
779                                 DBUS_TYPE_INT32, &sending_info->request_id,
780                                 DBUS_TYPE_INVALID);
781
782                 if (result == BLUETOOTH_ERROR_CANCEL_BY_USER) {
783                         BT_ERR("result is not BLUETOOTH_ERROR_NONE");
784                         __bt_sending_release();
785                         file_offset = 0;
786                 }
787         } else {
788                 retv_if(sending_info->sending_proxy == NULL,
789                                         BLUETOOTH_ERROR_INTERNAL);
790
791                 g_conn = _bt_get_session_gconn();
792                 retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
793
794                 client_proxy =  dbus_g_proxy_new_for_name(g_conn, BT_OBEX_SERVICE_NAME,
795                                                 BT_OBEX_CLIENT_PATH, BT_OBEX_CLIENT_INTERFACE);
796                 retv_if(client_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
797
798                 dbus_g_proxy_cancel_call(client_proxy,
799                                         sending_info->sending_proxy);
800
801                 g_idle_add(__bt_cancel_push_cb, NULL);
802         }
803
804         BT_DBG("-");
805
806         return BLUETOOTH_ERROR_NONE;
807 }
808
809 int _bt_opp_client_cancel_all_transfers(void)
810 {
811         BT_DBG("+");
812         if (transfer_list) {
813                 g_slist_free_full(transfer_list,
814                         (GDestroyNotify)__bt_free_sending_data);
815
816                 transfer_list = NULL;
817         }
818
819         _bt_opp_client_cancel_push();
820         BT_DBG("-");
821         return BLUETOOTH_ERROR_NONE;
822 }
823
824 int _bt_opp_client_is_sending(gboolean *sending)
825 {
826         BT_CHECK_PARAMETER(sending, return);
827
828         *sending = sending_info ? TRUE : FALSE;
829
830         return BLUETOOTH_ERROR_NONE;
831 }
832
833 void _bt_opp_client_check_pending_transfer(const char *address)
834 {
835         BT_DBG("+");
836
837         int result = BLUETOOTH_ERROR_CANCEL;
838
839         ret_if(sending_info == NULL);
840         ret_if(sending_info->transfer_info == NULL);
841
842         if (g_strcmp0(sending_info->address, address) == 0) {
843                 BT_INFO("Address Match.Cancel current transfer");
844                 sending_info->transfer_info->transfer_status = BT_TRANSFER_STATUS_COMPLETED;
845                 sending_info->result = result;
846
847                 if (!sending_info->is_canceled) {
848                         _bt_send_event(BT_OPP_CLIENT_EVENT,
849                                         BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE,
850                                         DBUS_TYPE_INT32, &result,
851                                         DBUS_TYPE_STRING, &sending_info->transfer_info->file_name,
852                                         DBUS_TYPE_UINT64, &sending_info->transfer_info->size,
853                                         DBUS_TYPE_INT32, &sending_info->request_id,
854                                         DBUS_TYPE_INVALID);
855
856                         __bt_free_transfer_info(sending_info->transfer_info);
857                         sending_info->transfer_info = NULL;
858                         /* Reset the file offset as we will cancelled remaining files also */
859                         file_offset = 0;
860                 }
861
862                 _bt_send_event(BT_OPP_CLIENT_EVENT,
863                                 BLUETOOTH_EVENT_OPC_DISCONNECTED,
864                                 DBUS_TYPE_INT32, &sending_info->result,
865                                 DBUS_TYPE_STRING, &sending_info->address,
866                                 DBUS_TYPE_INT32, &sending_info->request_id,
867                                 DBUS_TYPE_INVALID);
868
869                 __bt_sending_release();
870         }
871         BT_DBG("-");
872 }