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