Initial refactoring merge
[platform/core/telephony/telephony-daemon.git] / src / main.c
1 /*
2  * telephony-daemon
3  *
4  * Copyright 2013 Samsung Electronics Co. Ltd.
5  * Copyright 2013 Intel Corporation.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23
24 #include <dlfcn.h>
25 #include <getopt.h>
26 #include <sys/stat.h>
27 #include <sys/sysinfo.h>
28 #include <systemd/sd-daemon.h>
29
30 #include <glib.h>
31 #include <dlog.h>
32
33 #ifdef ENABLE_MONITOR
34 #include "monitor.h"
35 #endif
36
37 #include <tcore.h>
38 #include <server.h>
39 #include <plugin.h>
40
41 #ifndef DAEMON_VERSION
42 #define DAEMON_VERSION "unknown"
43 #endif
44
45 #ifndef DEFAULT_PLUGINS_PATH
46 #define DEFAULT_PLUGINS_PATH "/usr/lib/telephony/plugins/"
47 #endif
48
49 #define NOTUSED(var) (var = var)
50
51 static Server *_server = NULL;
52
53 static void __usage_info(const gchar *exec)
54 {
55         printf("Usage: %s [OPTION]... [PLUGIN_PATH]\n", exec);
56         printf("\n");
57         printf("  -T, --testload\t run with plugin load test mode and exit\n");
58         printf("  -h, --help\t\t display this help and exit\n");
59         printf("\n");
60 }
61
62 void tcore_log(enum tcore_log_type type, enum tcore_log_priority priority, const gchar *tag, const gchar *fmt, ...)
63 {
64         va_list ap;
65         gchar buf[1024];
66
67         va_start(ap, fmt);
68         vsnprintf(buf, 1023, fmt, ap);
69         va_end(ap);
70
71         __dlog_print(type, priority, tag, buf);
72 }
73
74 static void glib_log(const gchar *log_domain, GLogLevelFlags log_level,
75                 const gchar *msg, gpointer user_data)
76 {
77         NOTUSED(log_domain);
78         NOTUSED(log_level);
79         NOTUSED(user_data);
80
81         __dlog_print (LOG_ID_RADIO, DLOG_ERROR, "GLIB", msg);
82 }
83
84 #ifdef ENABLE_MONITOR
85 static void telephony_signal_handler(gint signo)
86 {
87         if (_server == NULL) {
88                 err("Server is NULL");
89                 return;
90         }
91
92         switch (signo) {
93         case SIGUSR1: {
94                 monitor_server_state(_server);
95         } break;
96
97         case SIGTERM: {
98                 tcore_server_free(_server);
99         } break;
100
101         default: {
102                 warn("*~*~*~* Unhandled Signal: [%d] *~*~*~*", signo);
103         } break;
104         } /* end switch */
105 }
106 #endif
107
108 static void __log_uptime()
109 {
110         float a = 0.00, b = 0.00;
111         FILE *fp = fopen("/proc/uptime", "r");
112         g_return_if_fail(NULL != fp);
113
114         info("Scanned %d items", fscanf(fp, "%f %f", &a, &b));
115         info("proc uptime = %f idletime = %f\n", a, b);
116
117         fclose(fp);
118 }
119
120 static gboolean __init_plugin(TcorePlugin *plugin)
121 {
122         const struct tcore_plugin_define_desc *desc = tcore_plugin_get_description(plugin);
123
124         if ((desc == NULL) || (desc->init == NULL)) {
125                 err("desc: [%p] desc->init: [%p]", desc, (desc ? desc->init : NULL));
126                 return FALSE;
127         }
128
129         if (desc->init(plugin) == FALSE) {              /* TODO: Remove plugin from server */
130                 gchar *plugin_name = tcore_plugin_get_filename(plugin);
131                 if (plugin_name != NULL) {
132                         err("Plug-in '%s' init failed!!!", plugin_name);
133                         tcore_free(plugin_name);
134                 }
135                 return FALSE;
136         }
137
138         return TRUE;
139 }
140
141 static gboolean init_plugins(Server *s)
142 {
143         GSList *list = tcore_server_ref_plugins(s);
144
145         while (list != NULL) {
146                 if (G_UNLIKELY(FALSE == __init_plugin(list->data))) {
147                         list = g_slist_next(list);
148                         continue;
149                 }
150                 list = g_slist_next(list);
151         }
152
153         info("[TIME_CHECK] plugin init finished");
154         return TRUE;
155 }
156
157 static void *__load_plugin(const gchar *filename, struct tcore_plugin_define_desc **desc_out)
158 {
159         void *handle;
160         struct tcore_plugin_define_desc *desc;
161         struct stat stat_buf;
162         gchar file_date[27];
163
164         handle = dlopen(filename, RTLD_NOW);
165         if (G_UNLIKELY(NULL == handle)) {
166                 err("Failed to open '%s': %s", filename, dlerror());
167                 return NULL;
168         }
169
170         desc = dlsym(handle, "plugin_define_desc");
171         if (G_UNLIKELY(NULL == desc)) {
172                 err("Failed to load symbol: %s", dlerror());
173
174                 dlclose(handle);
175                 return NULL;
176         }
177
178         dbg("'%s' plugin", desc->name);
179         dbg(" - path = %s", filename);
180         dbg(" - version = %d", desc->version);
181         dbg(" - priority = %d", desc->priority);
182
183         memset(&stat_buf, 0x00, sizeof(stat_buf));
184         memset(&file_date, '\0', sizeof(file_date));
185
186         if (stat(filename, &stat_buf) == 0) {
187                 if (ctime_r(&stat_buf.st_mtime, file_date) != NULL) {
188                         if (strlen(file_date) > 1)
189                                 file_date[strlen(file_date)-1] = '\0';
190
191                         dbg(" - date = %s", file_date);
192                 }
193         }
194
195         if (G_LIKELY(desc->load)) {
196                 if (G_UNLIKELY(desc->load() == FALSE)) {
197                         warn("Failed to load Plug-in");
198
199                         dlclose(handle);
200                         return NULL;
201                 }
202         }
203
204         if (desc_out != NULL)
205                 *desc_out = desc;
206
207         return handle;
208 }
209
210 static gboolean load_plugins(Server *s, const gchar *path, gboolean flag_test_load)
211 {
212         const gchar *file = NULL;
213         gchar *filename = NULL;
214         GDir *dir = NULL;
215         void *handle = NULL;
216         struct tcore_plugin_define_desc *desc = NULL;
217
218         if ((path == NULL) || (s == NULL)) {
219                 err("path: [%p] s: [%p]", path, s);
220                 return FALSE;
221         }
222
223         dir = g_dir_open(path, 0, NULL);
224         if (dir == NULL) {
225                 err("Failed to open directory '%s'", path);
226                 return FALSE;
227         }
228
229         while ((file = g_dir_read_name(dir)) != NULL) {
230                 if (g_str_has_prefix(file, "lib") == TRUE
231                                 || g_str_has_suffix(file, ".so") == FALSE)
232                         continue;
233
234                 filename = g_build_filename(path, file, NULL);
235
236                 /* Load a plugin */
237                 if (G_UNLIKELY((handle = __load_plugin(filename, &desc)) == NULL)) {
238                         g_free(filename);
239                         continue;
240                 }
241
242                 /* Don't add to server if flag_test_load */
243                 if (flag_test_load) {
244                         dbg("Loading '%s' - Successful", filename);
245
246                         dlclose(handle);
247                         g_free(filename);
248                         continue;
249                 }
250
251                 /* Add Plug-in to Server Plug-in list */
252                 tcore_server_add_plugin(s, tcore_plugin_new(s, desc, filename, handle));
253                 dbg("'%s' added", desc->name);
254
255                 g_free(filename);
256         }
257
258         g_dir_close(dir);
259         info("[TIME_CHECK] Plug-in load finished");
260
261         return TRUE;
262 }
263
264 gint main(gint argc, gchar *argv[])
265 {
266 #ifdef ENABLE_MONITOR
267         struct sigaction sigact;
268 #endif
269         Server *s;
270         gboolean flag_test_load = FALSE;
271         gint opt = 0, opt_index = 0, ret_code = EXIT_SUCCESS;
272         struct option options[] = {
273                 { "help", 0, 0, 0 },
274                 { "testload", 0, &flag_test_load, 1 },
275                 { 0, 0, 0, 0 }
276         };
277         gchar *plugin_path = DEFAULT_PLUGINS_PATH;
278         gchar *tcore_ver = NULL;
279         struct sysinfo sys_info;
280
281         /* System Uptime */
282         if (sysinfo(&sys_info) == 0)
283                 info("uptime: %ld secs", sys_info.uptime);
284         __log_uptime();
285
286         /* Version Info */
287         tcore_ver = tcore_util_get_version();
288         info("daemon version: %s", DAEMON_VERSION);
289         info("libtcore version: %s", tcore_ver);
290         tcore_free(tcore_ver);
291         info("glib version: %u.%u.%u", glib_major_version, glib_minor_version, glib_micro_version);
292
293 #ifdef ENABLE_MONITOR
294         /* Signal Registration */
295         sigact.sa_handler = telephony_signal_handler;
296         sigemptyset(&sigact.sa_mask);
297         sigact.sa_flags = 0;
298         if (sigaction(SIGTERM, &sigact, NULL) < 0)
299                 warn("sigaction(SIGTERM) failed.");
300         if (sigaction(SIGUSR1, &sigact, NULL) < 0)
301                 warn("sigaction(SIGUSR1) failed.");
302
303         /* Additional signals for dedugging the cause of Telephony crash */
304         if (sigaction(SIGINT, &sigact, NULL) < 0)
305                 warn("sigaction(SIGINT) failed.");
306         if (sigaction(SIGABRT, &sigact, NULL) < 0)
307                 warn("sigaction(SIGABRT) failed.");
308         if (sigaction(SIGHUP, &sigact, NULL) < 0)
309                 warn("sigaction(SIGHUP) failed.");
310         if (sigaction(SIGSEGV, &sigact, NULL) < 0)
311                 warn("sigaction(SIGSEGV) failed.");
312         if (sigaction(SIGXCPU, &sigact, NULL) < 0)
313                 warn("sigaction(SIGXCPU) failed.");
314         if (sigaction(SIGQUIT, &sigact, NULL) < 0)
315                 warn("sigaction(SIGQUIT) failed.");
316 #endif
317
318         /* Commandline option parser TODO: Replace with GOptionContext */
319         while (TRUE) {
320                 opt = getopt_long(argc, argv, "hT", options, &opt_index);
321                 if (opt == -1)
322                         break;
323
324                 switch (opt) {
325                 case 0: {
326                         switch (opt_index) {
327                         case 0: {
328                                 __usage_info(argv[0]);
329                                 return 0;
330                         } break;
331                         } /* end switch */
332                 } break;
333
334                 case 'h': {
335                         __usage_info(argv[0]);
336                         return 0;
337                 } break;
338
339                 case 'T': {
340                         flag_test_load = TRUE;
341                 } break;
342                 } /* end switch */
343         }
344
345         if (optind < argc)
346                 plugin_path = argv[optind];
347
348         info("plugin_path: [%s]", plugin_path);
349
350 #if !GLIB_CHECK_VERSION(2, 35, 0)
351         g_type_init();
352 #endif
353 #if !GLIB_CHECK_VERSION(2, 31, 0)
354         g_thread_init(NULL);
355 #endif
356
357         s = tcore_server_new();
358         if (G_UNLIKELY(NULL == s)) {
359                 err("server_new failed.");
360                 return EXIT_FAILURE;
361         }
362         _server = s;
363
364         g_log_set_default_handler(glib_log, s);
365
366         /* Load Plugins */
367         if (G_UNLIKELY(FALSE == load_plugins(s, (const gchar *)plugin_path, flag_test_load))) {
368                 err("load_plugins failed.");
369                 ret_code = EXIT_FAILURE;
370                 goto END;
371         }
372
373         if (flag_test_load) {
374                 ret_code = EXIT_SUCCESS;
375                 goto END;
376         }
377
378         /* Initialize Plugins */
379         if (G_UNLIKELY(FALSE == init_plugins(s))) {
380                 err("init_plugins failed.");
381                 ret_code = EXIT_FAILURE;
382                 goto END;
383         }
384
385         info("Server mainloop start");
386
387         /* Notification to systemd */
388         sd_notify(0, "READY=1");
389
390         /* Server Run */
391         if (G_UNLIKELY(FALSE == tcore_server_run(s))) {
392                 err("Server_run - Failed!!!");
393                 ret_code = EXIT_FAILURE;
394         }
395
396 END:
397         tcore_server_free(s);
398
399         return ret_code;
400 }