Set LE scanning mode to true only in case of success
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-obex-server.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 <stdio.h>
25 #include <glib.h>
26 #include <dlog.h>
27 #include <string.h>
28 #include <dirent.h>
29 #ifdef TIZEN_MDM_ENABLE
30 #include <bt-service-mdm.h>
31 #endif
32 #include <vconf.h>
33
34 #include <gio/gio.h>
35
36 #include "bluetooth-api.h"
37 #include "bt-internal-types.h"
38
39 #include "bt-service-common.h"
40 #include "bt-service-event.h"
41 #include "bt-service-util.h"
42 #include "bt-service-obex-agent.h"
43 #include "bt-service-obex-server.h"
44 #include "bt-service-agent.h"
45
46 #define DBUS_TIMEOUT 20 * 1000 /* 20 Seconds */
47 #define BT_OBEX_SERVER_AGENT_PATH "/org/obex/server_agent"
48
49 #define BT_OBEX_SERVICE "org.bluez.obex"
50 #define BT_OBEX_MANAGER "org.bluez.obex.AgentManager1"
51 #define BT_OBEX_PATH "/org/bluez/obex"
52
53
54 typedef struct {
55         char *filename;
56         char *file_path;
57         char *path;
58         char *type;
59         char *device_name;
60         int transfer_id;
61         gint64 file_size;
62         char *address;
63 } bt_transfer_info_t;
64
65 typedef struct {
66         GDBusMethodInvocation *reply_context;
67         guint64 file_size;
68         char *filename;
69         char *file_path;
70         char *device_name;
71         char *transfer_path;
72         char *address;
73 } bt_auth_info_t;
74
75 typedef struct {
76         char *dest_path;
77         char *sender;
78         int app_pid;
79 } bt_server_info_t;
80
81 typedef struct {
82         GDBusProxy *proxy;
83         int server_type;
84         int accept_id;
85         bt_auth_info_t *auth_info;
86         bt_server_info_t *native_server;
87         bt_server_info_t *custom_server;
88 } bt_obex_agent_info_t;
89
90 static GSList *transfers;
91 static bt_obex_agent_info_t agent_info;
92
93 static GQuark __bt_obex_error_quark(void)
94 {
95         static GQuark quark = 0;
96         if (!quark)
97                 quark = g_quark_from_static_string("agent");
98
99         return quark;
100 }
101
102 static bt_transfer_info_t *__bt_find_transfer_by_id(int transfer_id)
103 {
104         GSList *l;
105         bt_transfer_info_t *transfer;
106
107         for (l = transfers; l != NULL; l = l->next) {
108                 transfer = l->data;
109
110                 if (transfer == NULL)
111                         continue;
112
113                 if (transfer->transfer_id == transfer_id)
114                         return transfer;
115         }
116
117         return NULL;
118 }
119
120 bt_transfer_info_t *__bt_find_transfer_by_address(const char *address)
121 {
122         BT_DBG("+");
123         GSList *l;
124         bt_transfer_info_t *transfer;
125
126         retv_if(address == NULL, NULL);
127
128         for (l = transfers; l != NULL; l = l->next) {
129                 transfer = l->data;
130
131                 if (transfer == NULL)
132                         continue;
133
134                 if (g_strcmp0(transfer->address, address) == 0)
135                         return transfer;
136         }
137         BT_DBG("-");
138         return NULL;
139 }
140
141 static bt_transfer_info_t *__bt_find_transfer_by_path(const char *transfer_path)
142 {
143         GSList *l;
144         bt_transfer_info_t *transfer;
145
146         retv_if(transfer_path == NULL, NULL);
147
148         for (l = transfers; l != NULL; l = l->next) {
149                 transfer = l->data;
150
151                 if (transfer == NULL)
152                         continue;
153
154                 if (g_strcmp0(transfer->path, transfer_path) == 0)
155                         return transfer;
156         }
157
158         return NULL;
159 }
160
161 static void __bt_free_server_info(bt_server_info_t *server_info)
162 {
163         ret_if(server_info == NULL);
164
165         g_free(server_info->sender);
166         g_free(server_info->dest_path);
167         g_free(server_info);
168 }
169
170 static void __bt_free_auth_info(bt_auth_info_t *auto_info)
171 {
172         ret_if(auto_info == NULL);
173
174         g_free(auto_info->filename);
175         g_free(auto_info->transfer_path);
176         g_free(auto_info->device_name);
177         g_free(auto_info->address);
178         g_free(auto_info);
179 }
180
181 static void __bt_free_transfer_info(bt_transfer_info_t *transfer_info)
182 {
183         ret_if(transfer_info == NULL);
184
185         g_free(transfer_info->path);
186         g_free(transfer_info->filename);
187         g_free(transfer_info->file_path);
188         g_free(transfer_info->type);
189         g_free(transfer_info->device_name);
190         g_free(transfer_info->address);
191         g_free(transfer_info);
192 }
193
194 void _bt_obex_check_pending_transfer(const char *address)
195 {
196         BT_DBG("+");
197         GVariant *param = NULL;
198         bt_transfer_info_t *transfer_info = __bt_find_transfer_by_address(address);
199         if (transfer_info != NULL) {
200                 int result = BLUETOOTH_ERROR_CANCEL;
201                 param = g_variant_new("(isssstii)", result,
202                                         transfer_info->filename,
203                                         transfer_info->type,
204                                         transfer_info->device_name,
205                                         transfer_info->file_path,
206                                         transfer_info->file_size,
207                                         transfer_info->transfer_id,
208                                         agent_info.server_type);
209                 _bt_send_event(BT_OPP_SERVER_EVENT,
210                         BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_COMPLETED,
211                         param);
212                 transfers = g_slist_remove(transfers, transfer_info);
213                 __bt_free_transfer_info(transfer_info);
214         }
215         BT_DBG("-");
216 }
217
218 static char *__bt_get_remote_device_name(const char *bdaddress)
219 {
220         char *device_path = NULL;
221         char *name = NULL;
222         GVariant *value;
223         GVariant *result = NULL;
224         GError *err = NULL;
225         GDBusProxy *device_proxy;
226         GDBusConnection *conn;
227
228         retv_if(bdaddress == NULL, NULL);
229
230         device_path = _bt_get_device_object_path((char *)bdaddress);
231         retv_if(device_path == NULL, NULL);
232
233         conn = _bt_get_session_gconn();
234         retv_if(conn == NULL, NULL);
235         BT_INFO("Device_path %s", device_path);
236         device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
237                                                 NULL, BT_BLUEZ_NAME,
238                                                 device_path,
239                                                 BT_PROPERTIES_INTERFACE,
240                                                 NULL, &err);
241
242         g_free(device_path);
243         retv_if(device_proxy == NULL, NULL);
244
245         result = g_dbus_proxy_call_sync(device_proxy, "GetAll",
246                         g_variant_new("(s)", BT_DEVICE_INTERFACE),
247                         G_DBUS_CALL_FLAGS_NONE,
248                         DBUS_TIMEOUT, NULL,
249                         &err);
250         if (err) {
251                 BT_ERR("DBus Error : %s", err->message);
252                 g_clear_error(&err);
253                 return NULL;
254         }
255         if (result == NULL) {
256                 BT_ERR("g_dbus_proxy_call_sync function return NULL");
257                 return NULL;
258         }
259         g_variant_get(result, "(@a{sv})", &value);
260         g_variant_unref(result);
261
262         g_object_unref(device_proxy);
263         if (value) {
264                 GVariant *temp_value = g_variant_lookup_value(value, "Alias",
265                         G_VARIANT_TYPE_STRING);
266                 g_variant_get(temp_value, "(s)", &name);
267                 if (temp_value)
268                         g_variant_unref(temp_value);
269                 BT_INFO("Alias Name: %s", name);
270         }
271
272         return name;
273 }
274
275 static int __bt_get_transfer_id(const char *path)
276 {
277         char *tmp = NULL;
278         if (path == NULL)
279                 return -1;
280
281         tmp = strrchr(path, 'r') + 1;
282         retv_if(tmp == NULL, -1);
283
284         return atoi(tmp);
285 }
286
287 static GDBusProxy *__bt_get_transfer_proxy(const char *transfer_path)
288 {
289         GDBusConnection *conn;
290         GDBusProxy *proxy;
291         GError *err = NULL;
292
293         conn = _bt_get_session_gconn();
294         retv_if(conn == NULL, NULL);
295
296         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
297                                         NULL, BT_OBEX_SERVICE_NAME,
298                                         transfer_path,
299                                         BT_OBEX_TRANSFER_INTERFACE,
300                                         NULL, &err);
301
302         if (err) {
303                 BT_ERR("Error : %s", err->message);
304                 g_clear_error(&err);
305                 return NULL;
306         }
307
308         return proxy;
309 }
310
311 static GDBusProxy *__bt_get_transfer_properties_proxy(const char *transfer_path)
312 {
313         GDBusConnection *conn;
314         GDBusProxy *proxy;
315         GError *err = NULL;
316         conn = _bt_get_session_gconn();
317         retv_if(conn == NULL, NULL);
318
319         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
320                                         NULL,BT_OBEX_SERVICE_NAME,
321                                         transfer_path,
322                                         BT_PROPERTIES_INTERFACE,
323                                         NULL, &err);
324         if (err) {
325                 BT_ERR("Error : %s", err->message);
326                 g_clear_error(&err);
327                 return NULL;
328         }
329         return proxy;
330 }
331
332 static int __bt_get_transfer_properties(bt_transfer_info_t *transfer_info,
333                                         const char *transfer_path)
334 {
335         GDBusProxy *transfer_proxy;
336         char *bdaddress = NULL;
337         GVariant *result = NULL;
338         GError *err = NULL;
339         GVariantIter *iter = NULL;
340         BT_CHECK_PARAMETER(transfer_info, return);
341         BT_CHECK_PARAMETER(transfer_path, return);
342
343         transfer_proxy = __bt_get_transfer_properties_proxy(transfer_path);
344
345         retv_if(transfer_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
346
347         result = g_dbus_proxy_call_sync(transfer_proxy, "GetAll",
348                         g_variant_new("(s)", BT_OBEX_TRANSFER_INTERFACE),
349                         G_DBUS_CALL_FLAGS_NONE,
350                         DBUS_TIMEOUT, NULL,
351                         &err);
352
353         if (err) {
354                 BT_ERR("DBus Error : %s", err->message);
355                 g_clear_error(&err);
356                 goto fail;
357         }
358         if (result == NULL) {
359                 BT_ERR("g_dbus_proxy_call_sync function return NULL");
360                 goto fail;
361         }
362
363         g_variant_get(result, "(a{sv})", &iter);
364         g_variant_unref(result);
365         if (iter) {
366                 const gchar *key;
367                 GVariant *val;
368                 gsize len = 0;
369                 while (g_variant_iter_loop(iter, "{sv}", &key, &val)) {
370                         if (g_strcmp0(key, "Operation") == 0) {
371                                 transfer_info->type = g_variant_dup_string(val, &len);
372                         } else if (g_strcmp0(key, "Name") == 0) {
373                                 transfer_info->filename = g_variant_dup_string(val, &len);
374                         } else if (g_strcmp0(key, "Size") == 0) {
375                                 transfer_info->file_size = g_variant_get_uint64(val);
376                         } else if (g_strcmp0(key, "Address") == 0) {
377                                 transfer_info->address = g_variant_dup_string(val, &len);
378                                 BT_INFO("addressss %s", transfer_info->address);
379                         } else if (g_strcmp0(key, "Filename") == 0) {
380                                 transfer_info->file_path = g_variant_dup_string(val, &len);
381                                 if (!transfer_info->file_path)
382                                         transfer_info->file_path = g_strdup(transfer_info->filename);
383                         }
384                 }
385                 g_variant_iter_free(iter);
386                 if (transfer_info->type == NULL)
387                         goto fail;
388                 if (transfer_info->address == NULL)
389                         goto fail;
390
391                 transfer_info->device_name = __bt_get_remote_device_name(transfer_info->address);
392
393                 if (!transfer_info->device_name)
394                         transfer_info->device_name = g_strdup(bdaddress);
395                 transfer_info->path = g_strdup(transfer_path);
396                 transfer_info->transfer_id = __bt_get_transfer_id(transfer_path);
397         }
398
399         g_object_unref(transfer_proxy);
400         return BLUETOOTH_ERROR_NONE;
401
402 fail:
403         g_object_unref(transfer_proxy);
404         return BLUETOOTH_ERROR_INTERNAL;
405 }
406
407 static gboolean __bt_authorize_cb(GDBusMethodInvocation *context,
408                                         const char *path,
409                                         gpointer user_data)
410 {
411         char *device_name = NULL;
412         int result = BLUETOOTH_ERROR_NONE;
413         GDBusProxy *transfer_properties_proxy;
414         char * bdaddress = NULL;
415         GVariant *ret;
416         GVariantIter *iter;
417         GVariant *param = NULL;
418         GError *err = NULL;
419
420         BT_DBG(" path [%s] \n", path);
421
422         transfer_properties_proxy = __bt_get_transfer_properties_proxy(path);
423
424         retv_if(transfer_properties_proxy == NULL, FALSE);
425
426         ret = g_dbus_proxy_call_sync(transfer_properties_proxy, "GetAll",
427                         g_variant_new("(s)", BT_OBEX_TRANSFER_INTERFACE),
428                         G_DBUS_CALL_FLAGS_NONE,
429                         DBUS_TIMEOUT, NULL,
430                         &err);
431         if (err) {
432                 BT_ERR("DBus Error : %s", err->message);
433                 g_clear_error(&err);
434                 return FALSE;
435         }
436         if (ret == NULL) {
437                 BT_ERR("g_dbus_proxy_call_sync function return NULL");
438                 return FALSE;
439         }
440         g_variant_get(ret, "(a{sv})", &iter);
441         g_variant_unref(ret);
442         if (iter == NULL) {
443                 g_object_unref(transfer_properties_proxy);
444                 return FALSE;
445         }
446
447 #ifdef TIZEN_MDM_ENABLE
448         mdm_bt_allow_t mode = MDM_BT_ALLOWED;
449 #endif
450
451         __bt_free_auth_info(agent_info.auth_info);
452
453         agent_info.auth_info = g_malloc(sizeof(bt_auth_info_t));
454
455         memset(agent_info.auth_info, 0, sizeof(bt_auth_info_t));
456
457         agent_info.auth_info->reply_context = context;
458
459         agent_info.auth_info->transfer_path = g_strdup(path);
460
461         if (iter) {
462                 const gchar *key;
463                 GVariant *val;
464                 gsize len = 0;
465                 while (g_variant_iter_loop(iter, "{sv}", &key, &val)) {
466                         if (g_strcmp0(key, "Name") == 0) {
467                                 agent_info.auth_info->filename = g_variant_dup_string(val,&len);
468                         } else if (g_strcmp0(key, "Address") == 0) {
469                                 bdaddress = g_variant_dup_string(val, &len);
470                         } else if (g_strcmp0(key, "Size") == 0) {
471                                 agent_info.auth_info->file_size = g_variant_get_uint64(val);
472                         }
473                 }
474                 g_variant_iter_free(iter);
475         }
476
477         device_name = __bt_get_remote_device_name(bdaddress);
478
479         if (!device_name)
480                 device_name = g_strdup(bdaddress);
481
482         agent_info.auth_info->device_name = device_name;
483
484         g_object_unref(transfer_properties_proxy);
485
486         if (agent_info.server_type == BT_CUSTOM_SERVER) {
487                 /* No need to send the event */
488                 _bt_obex_server_accept_authorize(agent_info.auth_info->filename, FALSE);
489                 return TRUE;
490         }
491         param = g_variant_new("(ist)", result,
492                                 agent_info.auth_info->filename,
493                                 agent_info.auth_info->file_size);
494         _bt_send_event(BT_OPP_SERVER_EVENT,
495                 BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_AUTHORIZE,
496                 param);
497
498         return TRUE;
499 }
500
501 void _bt_obex_transfer_started(const char *transfer_path)
502 {
503         bt_transfer_info_t *transfer_info;
504         request_info_t *req_info;
505         GVariant *out_param1 = NULL;
506         GVariant *param = NULL;
507         int result = BLUETOOTH_ERROR_NONE;
508
509         BT_DBG("%s", transfer_path);
510
511         transfer_info = g_malloc0(sizeof(bt_transfer_info_t));
512
513         if (agent_info.auth_info != NULL
514              && g_strcmp0(transfer_path, agent_info.auth_info->transfer_path) == 0) {
515                 transfer_info->filename = g_strdup(agent_info.auth_info->filename);
516                 transfer_info->file_size = agent_info.auth_info->file_size;
517                 transfer_info->type = g_strdup(TRANSFER_PUT);
518                 transfer_info->path = g_strdup(agent_info.auth_info->transfer_path);
519                 transfer_info->device_name = g_strdup(agent_info.auth_info->device_name);
520                 transfer_info->transfer_id = __bt_get_transfer_id(transfer_path);
521                 transfer_info->file_path = agent_info.auth_info->file_path;
522                 transfer_info->address = g_strdup(agent_info.auth_info->address);
523         } else {
524                 if (__bt_get_transfer_properties(transfer_info, transfer_path) < 0) {
525                         BT_ERR("Get Properties failed");
526                         __bt_free_auth_info(agent_info.auth_info);
527                         __bt_free_transfer_info(transfer_info);
528                         agent_info.auth_info = NULL;
529                         return;
530                 }
531                 agent_info.server_type = BT_FTP_SERVER;
532         }
533
534         __bt_free_auth_info(agent_info.auth_info);
535         agent_info.auth_info = NULL;
536
537         if (agent_info.server_type == BT_CUSTOM_SERVER) {
538                 if (agent_info.custom_server == NULL) {
539                         __bt_free_transfer_info(transfer_info);
540                         return;
541                 }
542
543                 req_info = _bt_get_request_info(agent_info.accept_id);
544                 if (req_info == NULL || req_info->context == NULL) {
545                         BT_ERR("info is NULL");
546                         goto done;
547                 }
548
549                 agent_info.accept_id = 0;
550                 result = BLUETOOTH_ERROR_NONE;
551                 GArray *g_out_param1 = NULL;
552                 g_out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
553                 if (out_param1 == NULL) {
554                         out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
555                                         g_out_param1->data, g_out_param1->len,
556                                         TRUE, NULL, NULL);
557                 }
558
559                 g_dbus_method_invocation_return_value(req_info->context,
560                                 g_variant_new("(iv)", result, out_param1));
561                 g_array_free(g_out_param1, TRUE);
562                 _bt_delete_request_list(req_info->req_id);
563         }
564 done:
565         transfers = g_slist_append(transfers, transfer_info);
566
567         BT_DBG("Transfer id %d\n", transfer_info->transfer_id);
568         param = g_variant_new("(isstii)", result,
569                                 transfer_info->filename,
570                                 transfer_info->type,
571                                 transfer_info->file_size,
572                                 transfer_info->transfer_id,
573                                 agent_info.server_type);
574         _bt_send_event(BT_OPP_SERVER_EVENT,
575                 BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_STARTED,
576                 param);
577 }
578
579 void _bt_obex_transfer_progress(const char *transfer_path,
580                                         int transferred)
581 {
582         BT_DBG("+");
583         bt_transfer_info_t *transfer_info;
584         int progress = 0;
585         GVariant *param = NULL;
586         int result = BLUETOOTH_ERROR_NONE;
587
588         transfer_info = __bt_find_transfer_by_path(transfer_path);
589         ret_if(transfer_info == NULL);
590
591         progress = (int)(((gdouble)transferred /
592                         (gdouble)transfer_info->file_size) * 100);
593
594         param = g_variant_new("(isstiii)", result,
595                                 transfer_info->filename,
596                                 transfer_info->type,
597                                 transfer_info->file_size,
598                                 transfer_info->transfer_id,
599                                 progress,
600                                 agent_info.server_type);
601         _bt_send_event(BT_OPP_SERVER_EVENT,
602                 BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_PROGRESS,
603                 param);
604         BT_DBG("-");
605 }
606
607 void _bt_obex_transfer_completed(const char *transfer_path, gboolean success)
608 {
609         bt_transfer_info_t *transfer_info;
610         GVariant *param = NULL;
611         int result;
612         BT_DBG("Transfer [%s] Success [%d] \n", transfer_path, success);
613
614         result = (success == TRUE) ? BLUETOOTH_ERROR_NONE
615                                 : BLUETOOTH_ERROR_CANCEL;
616
617         transfer_info = __bt_find_transfer_by_path(transfer_path);
618
619         if (transfer_info == NULL) {
620                 BT_DBG("Very small files receiving case, did not get Active status from obexd");
621                 if (agent_info.auth_info == NULL ||
622                                 g_strcmp0(transfer_path,
623                                 agent_info.auth_info->transfer_path) != 0) {
624                         BT_ERR("auth_info is NULL, returning");
625                         return;
626                 }
627
628                 transfer_info = g_new0(bt_transfer_info_t, 1);
629
630                 transfer_info->filename = g_strdup(agent_info.auth_info->filename);
631                 transfer_info->file_size = agent_info.auth_info->file_size;
632                 transfer_info->type = g_strdup(TRANSFER_PUT);
633                 transfer_info->path = g_strdup(agent_info.auth_info->transfer_path);
634                 transfer_info->device_name = g_strdup(agent_info.auth_info->device_name);
635                 transfer_info->transfer_id = __bt_get_transfer_id(transfer_path);
636                 transfer_info->file_path = agent_info.auth_info->file_path;
637
638                 param = g_variant_new("(isstii)", result,
639                                         transfer_info->filename,
640                                         transfer_info->type,
641                                         transfer_info->file_size,
642                                         transfer_info->transfer_id,
643                                         agent_info.server_type);
644                 _bt_send_event(BT_OPP_SERVER_EVENT,
645                         BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_STARTED,
646                         param);
647         }
648         param = g_variant_new("(isssstii)", result,
649                                 transfer_info->filename,
650                                 transfer_info->type,
651                                 transfer_info->device_name,
652                                 transfer_info->file_path,
653                                 transfer_info->file_size,
654                                 transfer_info->transfer_id,
655                                 agent_info.server_type);
656         _bt_send_event(BT_OPP_SERVER_EVENT,
657                 BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_COMPLETED,
658                 param);
659         transfers = g_slist_remove(transfers, transfer_info);
660         __bt_free_transfer_info(transfer_info);
661 }
662
663 void _bt_obex_transfer_connected()
664 {
665         BT_DBG("+");
666
667         int result = BLUETOOTH_ERROR_NONE;
668         GVariant *param = NULL;
669
670         param = g_variant_new("(i)", result);
671
672         _bt_send_event(BT_OPP_SERVER_EVENT,
673                 BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_CONNECTED,
674                 param);
675         BT_DBG("-");
676 }
677
678 void _bt_obex_transfer_disconnected()
679 {
680         BT_DBG("+");
681
682         int result = BLUETOOTH_ERROR_NONE;
683         GVariant *param = NULL;
684
685         param = g_variant_new("(i)", result);
686         _bt_send_event(BT_OPP_SERVER_EVENT,
687                 BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_DISCONNECTED,
688                 param);
689         BT_DBG("-");
690 }
691
692 int _bt_register_obex_server(void)
693 {
694         GDBusConnection *g_conn;
695         GDBusProxy *manager_proxy;
696         GError *g_error = NULL;
697
698         /* Get the session bus. */
699         g_conn = _bt_get_session_gconn();
700         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
701
702         _bt_obex_agent_new(BT_OBEX_SERVER_AGENT_PATH);
703
704         _bt_obex_setup(BT_OBEX_SERVER_AGENT_PATH);
705
706         _bt_obex_set_authorize_cb(BT_OBEX_SERVER_AGENT_PATH,
707                                         __bt_authorize_cb, NULL);
708
709         manager_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
710                                                 NULL, BT_OBEX_SERVICE,
711                                                 BT_OBEX_PATH,
712                                                 BT_OBEX_MANAGER,
713                                                 NULL, &g_error);
714
715         if (manager_proxy == NULL) {
716                 return BLUETOOTH_ERROR_INTERNAL;
717         }
718
719         g_dbus_proxy_call_sync(manager_proxy, "RegisterAgent",
720                                 g_variant_new("(o)", BT_OBEX_SERVER_AGENT_PATH),
721                                 G_DBUS_CALL_FLAGS_NONE,
722                                 DBUS_TIMEOUT, NULL,
723                                 &g_error);
724
725         if (g_error != NULL) {
726                 BT_ERR("Agent registration failed: %s\n", g_error->message);
727                 g_object_unref(manager_proxy);
728                 g_error_free(g_error);
729                 return BLUETOOTH_ERROR_INTERNAL;
730         }
731
732         agent_info.proxy = manager_proxy;
733
734         return BLUETOOTH_ERROR_NONE;
735 }
736
737 int _bt_unregister_obex_server(void)
738 {
739         GError *g_error = NULL;
740
741         retv_if(agent_info.proxy == NULL,
742                                 BLUETOOTH_ERROR_INTERNAL);
743
744         g_dbus_proxy_call_sync(agent_info.proxy, "UnregisterAgent",
745                                 g_variant_new("(o)", BT_OBEX_SERVER_AGENT_PATH),
746                                 G_DBUS_CALL_FLAGS_NONE,
747                                 DBUS_TIMEOUT, NULL,
748                                 &g_error);
749         if (g_error != NULL) {
750                 BT_ERR("Agent unregistration failed: %s", g_error->message);
751                 g_error_free(g_error);
752         }
753         _bt_obex_agent_destroy(BT_OBEX_SERVER_AGENT_PATH);
754         g_object_unref(agent_info.proxy);
755         agent_info.proxy = NULL;
756
757         return BLUETOOTH_ERROR_NONE;
758 }
759
760 gboolean __bt_check_folder_path(const char *dest_path)
761 {
762         DIR *dp;
763
764         retv_if(dest_path == NULL, FALSE);
765
766         dp = opendir(dest_path);
767
768         if (dp == NULL) {
769                 BT_ERR("The directory does not exist");
770                 return FALSE;
771         }
772
773         closedir(dp);
774
775         return TRUE;
776 }
777
778 int _bt_obex_server_allocate(char *sender, const char *dest_path, int app_pid, gboolean is_native)
779 {
780         BT_DBG("+");
781         if (__bt_check_folder_path(dest_path) == FALSE)
782                 return BLUETOOTH_ERROR_INVALID_PARAM;
783
784         if (is_native == TRUE) {
785                 retv_if(agent_info.native_server,
786                                 BLUETOOTH_ERROR_DEVICE_BUSY);
787
788                 /* Force to change the control to native */
789                 agent_info.native_server = g_malloc0(sizeof(bt_server_info_t));
790                 agent_info.native_server->dest_path = g_strdup(dest_path);
791                 agent_info.native_server->sender = g_strdup(sender);
792                 agent_info.native_server->app_pid = app_pid;
793                 agent_info.server_type = BT_NATIVE_SERVER;
794                 _bt_unregister_osp_server_in_agent(BT_OBEX_SERVER, NULL);
795         } else {
796                 retv_if(agent_info.custom_server,
797                                 BLUETOOTH_ERROR_DEVICE_BUSY);
798
799                 /* Force to change the control to custom */
800                 agent_info.custom_server = g_malloc0(sizeof(bt_server_info_t));
801                 agent_info.custom_server->dest_path = g_strdup(dest_path);
802                 agent_info.custom_server->sender = g_strdup(sender);
803                 agent_info.custom_server->app_pid = app_pid;
804                 agent_info.server_type = BT_CUSTOM_SERVER;
805                 _bt_register_osp_server_in_agent(BT_OBEX_SERVER, NULL, NULL, -1);
806         }
807         BT_DBG("-");
808         return BLUETOOTH_ERROR_NONE;
809 }
810
811 int _bt_obex_server_deallocate(int app_pid, gboolean is_native)
812 {
813         if (is_native == TRUE) {
814                 retv_if(agent_info.native_server == NULL,
815                                 BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST);
816
817                 retv_if(agent_info.native_server->app_pid != app_pid,
818                                 BLUETOOTH_ERROR_ACCESS_DENIED);
819
820                 __bt_free_server_info(agent_info.native_server);
821                 agent_info.native_server = NULL;
822
823                 /* Change the control to custom */
824                 if (agent_info.custom_server) {
825                         agent_info.server_type = BT_CUSTOM_SERVER;
826                         _bt_register_osp_server_in_agent(BT_OBEX_SERVER,
827                                                         NULL, NULL, -1);
828                 }
829         } else {
830                 retv_if(agent_info.custom_server == NULL,
831                                 BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST);
832
833                 retv_if(agent_info.custom_server->app_pid != app_pid,
834                                 BLUETOOTH_ERROR_ACCESS_DENIED);
835
836                 __bt_free_server_info(agent_info.custom_server);
837                 agent_info.custom_server = NULL;
838
839                 _bt_unregister_osp_server_in_agent(BT_OBEX_SERVER, NULL);
840
841                 /* Change the control to native */
842                 if (agent_info.native_server)
843                         agent_info.server_type = BT_NATIVE_SERVER;
844         }
845
846         return BLUETOOTH_ERROR_NONE;
847 }
848
849 int _bt_obex_server_accept_authorize(const char *filename, gboolean is_native)
850 {
851         char file_path[BT_FILE_PATH_MAX] = { 0 };
852         bt_server_info_t *server_info;
853
854         BT_CHECK_PARAMETER(filename, return);
855
856         retv_if(agent_info.auth_info == NULL, BLUETOOTH_ERROR_INTERNAL);
857
858         retv_if(agent_info.auth_info->reply_context == NULL,
859                                 BLUETOOTH_ERROR_INTERNAL);
860
861         if (is_native == TRUE)
862                 server_info = agent_info.native_server;
863         else
864                 server_info = agent_info.custom_server;
865
866         retv_if(server_info == NULL, BLUETOOTH_ERROR_INTERNAL);
867
868         if (server_info->dest_path != NULL)
869                 snprintf(file_path, sizeof(file_path), "%s/%s",
870                         server_info->dest_path, filename);
871         else
872                 snprintf(file_path, sizeof(file_path), "%s", filename);
873
874         g_dbus_method_invocation_return_value(agent_info.auth_info->reply_context,
875                 g_variant_new("(s)",&file_path));
876         agent_info.auth_info->reply_context = NULL;
877         agent_info.auth_info->file_path = g_strdup(file_path);
878
879         return BLUETOOTH_ERROR_NONE;
880 }
881
882 int _bt_obex_server_reject_authorize(void)
883 {
884         GError *g_error;
885
886         retv_if(agent_info.auth_info->reply_context == NULL,
887                                 BLUETOOTH_ERROR_INTERNAL);
888
889         g_error = g_error_new(__bt_obex_error_quark(),
890                         BT_OBEX_AGENT_ERROR_CANCEL,
891                         "CancelledByUser");
892
893         g_dbus_method_invocation_return_gerror(agent_info.auth_info->reply_context,
894                         g_error);
895         g_error_free(g_error);
896
897         __bt_free_auth_info(agent_info.auth_info);
898         agent_info.auth_info = NULL;
899
900         return BLUETOOTH_ERROR_NONE;
901 }
902
903 int _bt_obex_server_set_destination_path(const char *dest_path,
904                                                 gboolean is_native)
905 {
906         bt_server_info_t *server_info;
907
908         BT_CHECK_PARAMETER(dest_path, return);
909
910         DIR *dp = NULL;
911
912         dp = opendir(dest_path);
913
914         if (dp == NULL) {
915                 BT_ERR("The directory does not exist");
916                 return BLUETOOTH_ERROR_INVALID_PARAM;
917         }
918
919         closedir(dp);
920
921         if (is_native == TRUE)
922                 server_info = agent_info.native_server;
923         else
924                 server_info = agent_info.custom_server;
925
926         retv_if(server_info == NULL,
927                         BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST);
928
929         g_free(server_info->dest_path);
930         server_info->dest_path = g_strdup(dest_path);
931
932         return BLUETOOTH_ERROR_NONE;
933 }
934
935 int _bt_obex_server_set_root(const char *root)
936 {
937         GError *g_error = NULL;
938         GVariant *folder = NULL;
939         char *string = "Root";
940         DIR *dp = NULL;
941
942         BT_CHECK_PARAMETER(root, return);
943
944         retv_if(agent_info.proxy == NULL,
945                                 BLUETOOTH_ERROR_INTERNAL);
946
947         dp = opendir(root);
948
949         if (dp == NULL) {
950                 BT_ERR("The directory does not exist");
951                 return BLUETOOTH_ERROR_INVALID_PARAM;
952         }
953
954         closedir(dp);
955
956         folder = g_variant_new_string(root);
957         g_dbus_proxy_call_sync(agent_info.proxy, "SetProperty",
958                         g_variant_new("(sv)", string, folder),
959                         G_DBUS_CALL_FLAGS_NONE,
960                         DBUS_TIMEOUT, NULL,
961                         &g_error);
962
963         if (g_error) {
964                 BT_ERR("SetProperty Fail: %s", g_error->message);
965                 g_error_free(g_error);
966                 return BLUETOOTH_ERROR_INTERNAL;
967         }
968
969         return BLUETOOTH_ERROR_NONE;
970 }
971
972 int _bt_obex_server_cancel_transfer(int transfer_id)
973 {
974         bt_transfer_info_t *transfer = NULL;
975         GDBusProxy *proxy;
976         GError *err = NULL;
977         BT_DBG("+");
978         transfer = __bt_find_transfer_by_id(transfer_id);
979
980         retv_if(transfer == NULL, BLUETOOTH_ERROR_NOT_FOUND);
981         proxy = __bt_get_transfer_proxy(transfer->path);
982
983         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
984
985         g_dbus_proxy_call_sync(proxy, "Cancel", NULL,
986                 G_DBUS_CALL_FLAGS_NONE,
987                 DBUS_TIMEOUT, NULL, &err);
988         if (err) {
989                 BT_ERR("Dbus Err: %s", err->message);
990                 g_clear_error(&err);
991         }
992         g_object_unref(proxy);
993
994         return BLUETOOTH_ERROR_NONE;
995 }
996
997 int _bt_obex_server_cancel_all_transfers(void)
998 {
999         GSList *l;
1000         bt_transfer_info_t *transfer;
1001
1002         for (l = transfers; l != NULL; l = l->next) {
1003                 transfer = l->data;
1004
1005                 if (transfer == NULL)
1006                         continue;
1007
1008                 _bt_obex_server_cancel_transfer(transfer->transfer_id);
1009         }
1010
1011         return BLUETOOTH_ERROR_NONE;
1012 }
1013
1014 int _bt_obex_server_is_activated(gboolean *activated)
1015 {
1016         BT_CHECK_PARAMETER(activated, return);
1017
1018         if (agent_info.custom_server) {
1019                 *activated = TRUE;
1020         } else {
1021                 *activated = FALSE;
1022         }
1023
1024         return BLUETOOTH_ERROR_NONE;
1025 }
1026
1027 int _bt_obex_server_check_allocation(gboolean *allocation)
1028 {
1029         BT_CHECK_PARAMETER(allocation, return);
1030
1031         if (agent_info.native_server || agent_info.custom_server) {
1032                 *allocation = TRUE;
1033         } else {
1034                 *allocation = FALSE;
1035         }
1036
1037         return BLUETOOTH_ERROR_NONE;
1038 }
1039
1040 int _bt_obex_server_check_termination(char *sender)
1041 {
1042         BT_CHECK_PARAMETER(sender, return);
1043
1044         if (agent_info.native_server) {
1045                 if (g_strcmp0(sender, agent_info.native_server->sender) == 0) {
1046                         _bt_obex_server_deallocate(agent_info.native_server->app_pid,
1047                                                 TRUE);
1048                 }
1049         }
1050
1051         if (agent_info.custom_server) {
1052                 if (g_strcmp0(sender, agent_info.custom_server->sender) == 0) {
1053                         _bt_obex_server_deallocate(agent_info.custom_server->app_pid,
1054                                                 FALSE);
1055                 }
1056         }
1057
1058         return BLUETOOTH_ERROR_NONE;
1059 }
1060
1061 int _bt_obex_server_is_receiving(gboolean *receiving)
1062 {
1063         BT_CHECK_PARAMETER(receiving, return);
1064
1065         if (transfers == NULL || g_slist_length(transfers) == 0) {
1066                 *receiving = FALSE;
1067         } else {
1068                 *receiving = TRUE;
1069         }
1070
1071         return BLUETOOTH_ERROR_NONE;
1072 }
1073
1074 gboolean __bt_obex_server_accept_timeout_cb(gpointer user_data)
1075 {
1076         request_info_t *req_info;
1077         GVariant *out_param1 = NULL;
1078         int result = BLUETOOTH_ERROR_TIMEOUT;
1079
1080         /* Already reply in _bt_obex_transfer_started */
1081         retv_if(agent_info.accept_id == 0, FALSE);
1082
1083         req_info = _bt_get_request_info(agent_info.accept_id);
1084         if (req_info == NULL || req_info->context == NULL) {
1085                 BT_ERR("info is NULL");
1086                 return FALSE;
1087         }
1088
1089         agent_info.accept_id = 0;
1090         GArray *g_out_param1 = NULL;
1091         g_out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
1092         if (out_param1 == NULL) {
1093                 out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
1094                                 g_out_param1->data, g_out_param1->len,
1095                                 TRUE, NULL, NULL);
1096         }
1097
1098         g_dbus_method_invocation_return_value(req_info->context,
1099                         g_variant_new("(iv)", result, out_param1));
1100         g_array_free(g_out_param1, TRUE);
1101         _bt_delete_request_list(req_info->req_id);
1102
1103         return FALSE;
1104 }
1105
1106 /* To support the BOT  */
1107 int _bt_obex_server_accept_connection(int request_id)
1108 {
1109         if (!_bt_agent_reply_authorize(TRUE))
1110                 return BLUETOOTH_ERROR_INTERNAL;
1111
1112         agent_info.accept_id = request_id;
1113
1114         g_timeout_add(BT_SERVER_ACCEPT_TIMEOUT,
1115                         (GSourceFunc)__bt_obex_server_accept_timeout_cb,
1116                         NULL);
1117
1118         return BLUETOOTH_ERROR_NONE;
1119 }
1120
1121 /* To support the BOT  */
1122 int _bt_obex_server_reject_connection(void)
1123 {
1124         if (!_bt_agent_reply_authorize(FALSE))
1125                 return BLUETOOTH_ERROR_INTERNAL;
1126
1127         return BLUETOOTH_ERROR_NONE;
1128 }
1129