33367f9945b04ffb9798e257cf3114943c06db71
[platform/core/connectivity/bluetooth-share.git] / bt-share / src / bt-share-main.c
1 /*
2  * bluetooth-share
3  *
4  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *              http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <glib.h>
21 #include <glib-object.h>
22 #include <string.h>
23 #include <appcore-efl.h>
24 #include <vconf.h>
25 #include <errno.h>
26 #include <sys/stat.h>
27
28 /* For multi-user support */
29 #include <tzplatform_config.h>
30
31 #include "applog.h"
32 #include "bt-share-main.h"
33 #include "bluetooth-api.h"
34 #include "obex-event-handler.h"
35 #include "bt-share-ipc.h"
36 #include "bt-share-noti-handler.h"
37 #include "bt-share-resource.h"
38 #include "bt-share-notification.h"
39 #include "bt-share-common.h"
40 #include "bt-share-cynara.h"
41 #include "bt-share-db.h"
42
43
44 #include <sys/types.h>
45 #include <unistd.h>
46 #include <grp.h>
47
48 #include "bluetooth-share-api.h"
49 #include "notification_internal.h"
50
51 #define BLUETOOTH_SHARE_BUS             "org.projectx.bluetooth.share"
52
53 static gboolean terminated;
54
55 GMainLoop *main_loop = NULL;
56 struct bt_appdata *app_state = NULL;
57
58 void _bt_terminate_bluetooth_share(void)
59 {
60         DBG("+");
61
62         if (main_loop) {
63                 g_main_loop_quit(main_loop);
64         } else {
65                 terminated = TRUE;
66         }
67         DBG("-");
68 }
69
70 static void __bt_release_service(struct bt_appdata *ad)
71 {
72         if (ad == NULL)
73                 return;
74
75         _bt_deinit_vconf_notification();
76         _bt_delete_notification(ad->send_noti);
77         _bt_delete_notification(ad->receive_noti);
78         _bt_delete_notification(ad->opc_noti);
79         _bt_clear_receive_noti_list();
80         ad->send_noti = NULL;
81         ad->receive_noti = NULL;
82         ad->opc_noti = NULL;
83
84         bluetooth_opc_deinit();
85         bluetooth_obex_server_deinit();
86         _bt_unregister_notification_cb(ad);
87
88         DBG("Terminating bluetooth-share daemon");
89 }
90
91 static void __bt_sigterm_handler(int signo)
92 {
93         DBG("+");
94
95         if (main_loop) {
96                 g_main_loop_quit(main_loop);
97         } else {
98                 terminated = TRUE;
99         }
100
101         DBG("-");
102 }
103
104 static void __bt_update_notification_status_values()
105 {
106         struct bt_appdata *ad = app_state;
107         GSList *tr_data_list = NULL;
108         GSList *list_iter = NULL;
109         bt_tr_data_t *info = NULL;;
110         char str[NOTIFICATION_TEXT_LEN_MAX] = { 0 };
111         notification_h noti = NULL;
112         sqlite3 *db = NULL;
113
114         /* Update notification status durning BT off */
115         if (_bt_update_notification_status(ad) == FALSE) {
116                 DBG("Notification item is not existed.");
117                 return;
118         }
119
120         DBG("Initialize transfer information");
121         db = bt_share_open_db();
122         if (!db)
123                 return;
124
125         tr_data_list = bt_share_get_all_tr_data_list(db, BT_DB_OUTBOUND);
126         if (NULL != tr_data_list) {
127                 list_iter = tr_data_list;
128
129                 while (NULL != list_iter) {
130                         info = list_iter->data;
131                         if (NULL == info)
132                                 break;
133
134                         if (info->tr_status == BT_TR_SUCCESS) {
135                                 ad->send_data.tr_success++;
136                         } else if (info->tr_status == BT_TR_FAIL) {
137                                 ad->send_data.tr_fail++;
138                         } else if (info->tr_status == BT_TR_ONGOING) {
139                         /* In case of ongoing file transfer if bluetooth is switched off
140                         we need to update the status to fail for these transaction */
141                                 ad->send_data.tr_fail++;
142                                 info->tr_status = BT_TR_FAIL;
143                                 bt_share_update_tr_data(db, BT_DB_OUTBOUND, info->id, info);
144                         } else {
145                                 ERR("Invalid status\n");
146                         }
147
148                         list_iter = g_slist_next(list_iter);
149                 }
150
151                 if ((ad->send_data.tr_success + ad->send_data.tr_fail) != 0) {
152                         snprintf(str, sizeof(str), "%s %d %d", BT_TR_STATUS,
153                         ad->send_data.tr_success, ad->send_data.tr_fail);
154
155                         noti = _bt_create_notification(BT_NOTI_T);
156                         //_bt_set_notification_app_launch(noti,
157                         //      CREATE_TR_LIST,
158                         //      NOTI_TR_TYPE_OUT, NULL, NULL);
159                         _bt_set_notification_property(noti, QP_NO_DELETE | QP_NO_TICKER);
160 //                      _bt_insert_notification(noti,
161 //                              BT_STR_SENT, str,
162 //                              BT_ICON_QP_SEND);
163                         ad->send_noti = noti;
164                 }
165
166                 bt_share_release_tr_data_list(tr_data_list);
167                 tr_data_list = NULL;
168                 list_iter = NULL;
169         }
170
171         tr_data_list = bt_share_get_all_tr_data_list(db, BT_DB_INBOUND);
172         if (NULL != tr_data_list) {
173                 list_iter = tr_data_list;
174
175                 while (NULL != list_iter) {
176                         info = list_iter->data;
177                         if (NULL == info)
178                                 break;
179
180                         if (info->tr_status == BT_TR_SUCCESS)
181                                 ad->recv_data.tr_success++;
182                         else
183                                 ad->recv_data.tr_fail++;
184
185                         list_iter = g_slist_next(list_iter);
186                 }
187
188                 if ((ad->recv_data.tr_success + ad->recv_data.tr_fail) != 0) {
189
190                         snprintf(str, sizeof(str), "%s %d %d", BT_TR_STATUS,
191                                 ad->recv_data.tr_success, ad->recv_data.tr_fail);
192                         DBG("str = [%s] \n", str);
193
194                         noti  = _bt_create_notification(BT_NOTI_T);
195                         //_bt_set_notification_app_launch(noti, CREATE_TR_LIST,
196                         //      NOTI_TR_TYPE_IN, NULL, NULL);
197                         _bt_set_notification_property(noti, QP_NO_DELETE | QP_NO_TICKER);
198 //                      _bt_insert_notification(noti,
199 //                              BT_STR_RECEIVED, str,
200 //                              BT_ICON_QP_RECEIVE);
201                         ad->receive_noti = noti;
202                 }
203
204                 bt_share_release_tr_data_list(tr_data_list);
205                 tr_data_list = NULL;
206                 list_iter = NULL;
207         }
208
209         bt_share_close_db(db);
210
211         return;
212 }
213
214 static notification_h __bt_update_notification_adapter_status(void)
215 {
216         notification_h noti;
217         notification_error_e ret;
218
219         noti  = _bt_create_notification(BT_NOTI_T);
220         if (!noti)
221                 return NULL;
222
223         ret = notification_set_property(noti, QP_NO_DELETE | QP_NO_TICKER);
224         if (ret != NOTIFICATION_ERROR_NONE) {
225                 goto failed;
226         }
227
228         ret = notification_set_application(noti, "ug-bluetooth-efl");
229         if (ret != NOTIFICATION_ERROR_NONE) {
230                 goto failed;
231         }
232
233         ret = notification_set_display_applist(noti,
234                          NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY);
235         if (ret != NOTIFICATION_ERROR_NONE) {
236                 goto failed;
237         }
238
239 //      _bt_insert_notification(noti,
240 //                      BT_STR_BLUETOOTH_ON, BT_STR_BLUETOOTH_AVAILABLE,
241 //                      BT_ICON_QP_BT_ON);
242         return noti;
243
244 failed:
245         ERR("Fail to register notification");
246         notification_free(noti);
247         return NULL;
248
249 }
250
251 static int __bt_lang_changed_cb(void *data, void *user_data)
252 {
253         if (appcore_set_i18n(BT_COMMON_PKG, BT_COMMON_RES) < 0)
254                 return -1;
255
256         return 0;
257 }
258
259 static gboolean __bt_dbus_request_name(void)
260 {
261         int ret_code = 0;
262         DBusConnection *conn;
263         DBusError err;
264
265         dbus_error_init(&err);
266
267         conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
268
269         if (dbus_error_is_set(&err))
270                 goto failed;
271
272         ret_code = dbus_bus_request_name(conn,
273                                         BLUETOOTH_SHARE_BUS,
274                                         DBUS_NAME_FLAG_DO_NOT_QUEUE,
275                                         &err);
276         if (dbus_error_is_set(&err))
277                 goto failed;
278
279         if(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER == ret_code) {
280                 dbus_connection_unref(conn);
281                 return TRUE;
282         }
283
284 failed:
285         if (dbus_error_is_set(&err)) {
286                 ERR("D-Bus Error: %s\n", err.message);
287                 dbus_error_free(&err);
288         }
289
290         if (!conn)
291                 dbus_connection_unref(conn);
292
293
294         return FALSE;
295 }
296
297 int _bt_init_obex_server(void)
298 {
299         char storage[STORAGE_PATH_LEN_MAX];
300
301         _bt_get_default_storage(storage);
302         if (bluetooth_obex_server_init(storage) !=
303                                         BLUETOOTH_ERROR_NONE) {
304                 DBG("Fail to init obex server");
305                 return BT_SHARE_FAIL;
306         }
307
308         bluetooth_obex_server_set_root(BT_FTP_FOLDER);
309
310         return BT_SHARE_ERROR_NONE;
311 }
312
313 void _bt_terminate_app(void)
314 {
315         if (main_loop) {
316                 g_main_loop_quit(main_loop);
317         }
318 }
319
320 void __bt_create_transfer_db(void)
321 {
322         struct stat sts;
323         int ret;
324
325         /* Check if the DB exists; if not, create it and initialize it */
326         ret = stat(BT_TRANSFER_DB, &sts);
327         if (ret == -1 && errno == ENOENT)
328         {
329                 DBG("DB %s doesn't exist, it needs to be created and initialized", BT_TRANSFER_DB);
330                 DBG("script path: %s", SCRIPT_INIT_DB);
331                 ret = system(SCRIPT_INIT_DB);
332                 if (ret != EXIT_SUCCESS)
333                         ERR("Exit code of epp not clean: %i", ret);
334         }
335 }
336
337 int main(void)
338 {
339         int ret;
340         struct bt_appdata ad;
341         DBG("Starting bluetooth-share daemon");
342         memset(&ad, 0, sizeof(struct bt_appdata));
343         app_state = &ad;
344
345         signal(SIGTERM, __bt_sigterm_handler);
346
347         __bt_create_transfer_db();
348
349         if (__bt_dbus_request_name() == FALSE) {
350                 DBG("Aleady dbus instance existed\n");
351                 exit(0);
352         }
353
354         ret = appcore_set_event_callback(APPCORE_EVENT_LANG_CHANGE, __bt_lang_changed_cb, NULL);
355         if(ret < 0)
356                 DBG("Failed to excute the change of language");
357
358
359         /* init internationalization */
360         if (appcore_set_i18n(BT_COMMON_PKG, BT_COMMON_RES) < 0)
361                 return -1;
362
363         uid_t network_user = 551; /* uid of network_fw */
364         gid_t network_group = 551; /* gid of network_fw */
365
366         initgroups("network_fw", network_group);
367         ret = setgid(network_group);
368         DBG("setgid return : %d", ret);
369         ret = setuid(network_user);
370         DBG("setuid return : %d", ret);
371
372         if (_bt_share_cynara_init()) {
373                 ERR("Failed to initialize Cynara.\n");
374                 return -1;
375         }
376
377         bluetooth_register_callback(_bt_share_event_handler, NULL);
378         ret = bluetooth_opc_init();
379         if (ret != BLUETOOTH_ERROR_NONE) {
380                 ERR("bluetooth_opc_init failed!!\n");
381                 return -1;
382         }
383
384         _bt_init_dbus_signal();
385         _bt_init_vconf_notification(&ad);
386         __bt_update_notification_status_values();
387         _bt_register_notification_cb(&ad);
388
389         if (_bt_init_obex_server() == BT_SHARE_ERROR_NONE)
390                 ad.obex_server_init = TRUE;
391
392         if (terminated == TRUE) {
393                 __bt_release_service(&ad);
394                 bluetooth_unregister_callback();
395                 return -1;
396         }
397
398         notification_h noti;
399         noti = __bt_update_notification_adapter_status();
400
401         main_loop = g_main_loop_new(NULL, FALSE);
402         g_main_loop_run(main_loop);
403
404         _bt_delete_notification(noti);
405         __bt_release_service(&ad);
406         bluetooth_unregister_callback();
407         _bt_share_cynara_finish();
408
409         return 0;
410 }