135a6f6d7788f652d89f28c9fd75943daff0f6cf
[platform/core/connectivity/zigbee-manager.git] / zigbee-daemon / zigbee-lib / src / zblib_service.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Contact: Suresh Kumar N (suresh.n@samsung.com)
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 #include <dlfcn.h>
20 #include <sys/stat.h>
21
22 #include <zblib.h>
23 #include <zblib_service.h>
24 #include <zblib_plugin.h>
25 #include <zblib_service_interface.h>
26
27 /**< ZigBee Service object */
28 struct zblib_service_type {
29         GMainLoop *main_loop; /**< Service main-loop */
30
31         GSList *interface_objs; /**< ZigBee Service interface objects */
32         GSList *plugins; /**< ZigBee plug-ins */
33
34         GHashTable *request_table; /**< Request Hash table */
35         guint request_id; /**< Request ID */
36 };
37
38 static void *__zblib_service_load_plugin(gchar *filename,
39         struct zblib_plugin_descriptor **descriptor_out)
40 {
41         struct zblib_plugin_descriptor *descriptor = NULL;
42         void *handle = NULL;
43         struct stat stat_buf;
44         char file_date[27];
45
46         if (G_UNLIKELY(NULL == descriptor_out)) {
47                 Z_LOGE("descriptor_out is NULL!!!");
48                 return FALSE;
49         }
50
51         /* Open .so */
52         handle = dlopen(filename, RTLD_LAZY);
53         if (G_UNLIKELY(NULL == handle)) {
54                 Z_LOGE("dlopen() failed:[%s]", filename);
55                 return NULL;
56         }
57
58         /* Get symbol - "zigbee_plugin_descriptor" */
59         descriptor = dlsym(handle, "zigbee_plugin_descriptor");
60         if (G_UNLIKELY(NULL == descriptor)) {
61                 Z_LOGE("dlsym() failed:[%s]", "plugin_define_desc");
62                 dlclose(handle);
63                 return NULL;
64         }
65
66         Z_LOGD("%s plugin", descriptor->name);
67         Z_LOGD(" - path = %s", filename);
68         Z_LOGD(" - version = %d", descriptor->version);
69
70         memset(&stat_buf, 0x00, sizeof(stat_buf));
71         memset(&file_date, '\0', sizeof(file_date));
72
73         if (0 == stat(filename, &stat_buf)) {
74                 if (NULL != ctime_r(&stat_buf.st_mtime, file_date)) {
75                         if (1 < strlen(file_date))
76                                 file_date[strlen(file_date)-1] = '\0';
77                         Z_LOGD(" - date = %s", file_date);
78                 }
79         }
80
81         /* Load plug-in */
82         if (G_LIKELY(descriptor->load)) {
83                 if (G_UNLIKELY(FALSE == descriptor->load())) {
84                         Z_LOGW("load() failed... Skip this plugin!");
85                         dlclose(handle);
86                         return NULL;
87                 } else {
88                         Z_LOGI("Plug-in (%s) loaded!", descriptor->name);
89                 }
90         }
91
92         *descriptor_out = descriptor;
93
94         return handle;
95 }
96
97 static gboolean __zblib_service_init_plugin(ZigBeePlugin *plugin)
98 {
99         const struct zblib_plugin_descriptor *descriptor = zblib_plugin_get_descriptor(plugin);
100
101         if ((NULL == descriptor) || (NULL == descriptor->init)) {
102                 Z_LOGE("descriptor OR init function is NULL!!!");
103                 return FALSE;
104         }
105
106         if (G_UNLIKELY(FALSE == descriptor->init(plugin))) {
107                 char *plugin_name = zblib_plugin_get_plugin_name(plugin);
108                 if (G_UNLIKELY(NULL != plugin_name)) {
109                         Z_LOGE("plugin(%s) init failed!", plugin_name);
110                         g_free(plugin_name);
111                 }
112                 return FALSE;
113         }
114
115         return TRUE;
116 }
117
118 static gboolean __zblib_service_unload_plugin(ZigBeePlugin *plugin)
119 {
120         const struct zblib_plugin_descriptor *descriptor = zblib_plugin_get_descriptor(plugin);
121         char *plugin_name = zblib_plugin_get_plugin_name(plugin);
122
123         if ((NULL == descriptor) || (NULL == descriptor->unload)) {
124                 Z_LOGE("descriptor OR unload function is NULL!!!");
125                 return FALSE;
126         }
127
128
129         descriptor->unload(plugin);
130         Z_LOGI("plugin(%s) unloaded!", plugin_name);
131
132         return TRUE;
133 }
134
135 ZigBeeService *zblib_service_new()
136 {
137         ZigBeeService *service;
138
139         service = g_malloc0(sizeof(struct zblib_service_type));
140
141         /* Create g-main loop */
142         service->main_loop = g_main_loop_new(NULL, FALSE);
143         if (G_UNLIKELY(NULL == service->main_loop)) {
144                 Z_LOGE("g-main loop creation failed!!!");
145                 g_free(service);
146                 return NULL;
147         }
148
149         /* Create request hash table */
150         service->request_table = g_hash_table_new_full(g_direct_hash,
151                 g_direct_equal, NULL, NULL);
152
153         return service;
154 }
155
156 void zblib_service_free(ZigBeeService *service)
157 {
158         if (NULL == service) {
159                 Z_LOGE("service is NULL");
160                 return;
161         }
162
163         /* Free plug-ins */
164         if (service->plugins) {
165                 g_slist_free(service->plugins);
166                 service->plugins = NULL;
167         }
168
169         /* Unref 'g-main loop' */
170         if (service->main_loop)
171                 g_main_loop_unref(service->main_loop);
172
173         g_free(service);
174 }
175
176 gboolean zblib_service_run(ZigBeeService *service)
177 {
178         if ((NULL == service) || (NULL == service->main_loop)) {
179                 Z_LOGE("service or mainloop is NULL");
180                 return FALSE;
181         }
182
183         g_main_loop_run(service->main_loop);
184
185         return TRUE;
186 }
187
188 gboolean zblib_service_exit(ZigBeeService *service)
189 {
190         if ((NULL == service) || (NULL == service->main_loop)) {
191                 Z_LOGE("service or mainloop is NULL");
192                 return FALSE;
193         }
194
195         g_main_loop_quit(service->main_loop);
196
197         return TRUE;
198 }
199
200 gboolean zblib_service_add_plugin(ZigBeeService *service, ZigBeePlugin *plugin)
201 {
202         gchar *plugin_name;
203
204         if ((NULL == service) || (plugin == NULL)) {
205                 Z_LOGE("service: [%p] plugin: [%p]", service, plugin);
206                 return FALSE;
207         }
208
209         plugin_name = zblib_plugin_get_plugin_name(plugin);
210
211         /* All plug-ins would be appended */
212         service->plugins = g_slist_append(service->plugins, plugin);
213         Z_LOGD("%s added", plugin_name);
214         g_free(plugin_name);
215
216         return TRUE;
217 }
218
219 gboolean zblib_service_remove_plugin(ZigBeeService *service, ZigBeePlugin *plugin)
220 {
221         if ((NULL == service) || (plugin == NULL)) {
222                 Z_LOGE("service: [%p] plugin: [%p]", service, plugin);
223                 return FALSE;
224         }
225
226         /* Specific vendor plug-in would be removed */
227         service->plugins = g_slist_remove(service->plugins, plugin);
228
229         return TRUE;
230 }
231
232 gboolean zblib_service_load_plugins(ZigBeeService *service, const char *plugin_path)
233 {
234         const gchar *file = NULL;
235         gchar *filename = NULL;
236         GDir *dir = NULL;
237         void *handle = NULL;
238         struct zblib_plugin_descriptor *descriptor = NULL;
239         ZigBeePlugin *plugin = NULL;
240         gboolean ret;
241
242         if ((NULL == service) || (NULL == plugin_path)) {
243                 Z_LOGE("service: [%p] plugin_path: [%p]", service, plugin_path);
244                 return FALSE;
245         }
246
247         /* Open plug-in directory */
248         dir = g_dir_open(plugin_path, 0, NULL);
249         if (G_UNLIKELY(dir == NULL)) {
250                 Z_LOGE("Directory open failed!");
251                 return FALSE;
252         }
253
254         /* Scan through all libraries in plug-in directory */
255         while ((file = g_dir_read_name(dir)) != NULL) {
256                 if ((g_str_has_prefix(file, "lib") == TRUE)
257                                 || (g_str_has_suffix(file, ".so") == FALSE))
258                         continue;
259
260                 filename = g_build_filename(plugin_path, file, NULL);
261
262                 /* Load plug-in */
263                 handle = __zblib_service_load_plugin(filename, &descriptor);
264                 if (G_UNLIKELY(NULL == handle)) {
265                         g_free(filename);
266                         continue;
267                 }
268
269                 /* Create new plug-in */
270                 plugin = zblib_plugin_new(service, filename, descriptor, handle);
271                 if (G_UNLIKELY(NULL == plugin)) {
272                         g_free(filename);
273                         continue;
274                 }
275
276                 /* Add new plug-in */
277                 ret = zblib_service_add_plugin(service, plugin);
278                 if (G_UNLIKELY(FALSE == ret)) {
279                         zblib_plugin_free(plugin);
280                 }
281
282                 g_free(filename);
283         }
284         g_dir_close(dir);
285
286         return TRUE;
287 }
288
289 gboolean zblib_service_initialize_plugins(ZigBeeService *service)
290 {
291         GSList *list;
292
293         if (NULL == service) {
294                 Z_LOGE("service is NULL");
295                 return FALSE;
296         }
297
298         /* Refer plug-in list */
299         list = zblib_service_ref_plugins(service);
300         while (list != NULL) {
301                 /* Initialize each plug-in */
302                 if (G_UNLIKELY(FALSE == __zblib_service_init_plugin((ZigBeePlugin *)(list->data)))) {
303                         list = g_slist_next(list);
304                         continue;
305                 }
306                 list = g_slist_next(list);
307         }
308
309         return TRUE;
310 }
311
312 gboolean zblib_service_unload_plugins(ZigBeeService *service)
313 {
314         GSList *list;
315
316         if (NULL == service) {
317                 Z_LOGE("service is NULL");
318                 return FALSE;
319         }
320
321         list = zblib_service_ref_plugins(service);
322         while (list != NULL) {
323                 ZigBeePlugin *plugin = list->data;
324
325                 /* Unload each plug-in */
326                 if (G_UNLIKELY(FALSE == __zblib_service_unload_plugin(plugin))) {
327                         list = g_slist_next(list);
328                         continue;
329                 }
330
331                 list = g_slist_next(list);
332                 zblib_service_remove_plugin(service, plugin);
333         }
334
335         return TRUE;
336 }
337
338 GSList *zblib_service_ref_plugins(ZigBeeService *service)
339 {
340         if (NULL == service) {
341                 Z_LOGE("service is NULL");
342                 return NULL;
343         }
344
345         return service->plugins;
346 }
347
348 gboolean zblib_service_add_service_interface(ZigBeeService *service,
349         ZigBeeServiceInterface *service_interface)
350 {
351         gchar *object_name;
352
353         if ((NULL == service) || (NULL == service_interface)) {
354                 Z_LOGE("service: [%p] service_interface: [%p]", service, service_interface);
355                 return FALSE;
356         }
357
358         object_name = zblib_service_interface_get_name(service_interface);
359
360         /*
361          * All service interface objects would be appended
362          */
363         service->interface_objs = g_slist_append(service->interface_objs, service_interface);
364         Z_LOGD("%s added", object_name);
365         g_free(object_name);
366
367         return TRUE;
368 }
369
370 gboolean zblib_service_remove_service_interface(ZigBeeService *service,
371         ZigBeeServiceInterface *service_interface)
372 {
373         if ((NULL == service) || (NULL == service_interface)) {
374                 Z_LOGE("service: [%p] service_interface: [%p]", service, service_interface);
375                 return FALSE;
376         }
377
378         /*
379          * service interface object would be removed
380          */
381         service->interface_objs = g_slist_remove(service->interface_objs, service_interface);
382
383         return TRUE;
384 }
385
386 ZigBeeServiceInterface *zblib_service_ref_service_interface(ZigBeeService *service,
387         const gchar *service_interface_name)
388 {
389         ZigBeeServiceInterface *service_interface = NULL;
390         ZigBeeServiceInterface *tmp_service_interface = NULL;
391         gchar *object_name;
392
393         GSList *list;
394
395         if ((NULL == service) || (NULL == service_interface_name)) {
396                 Z_LOGE("service: [%p] service_interface_name: [%p]", service, service_interface_name);
397                 return NULL;
398         }
399
400         list = service->interface_objs;
401         while (list) {
402                 tmp_service_interface = (ZigBeeServiceInterface *)list->data;
403
404                 /* Get object name of service_interface */
405                 object_name = zblib_service_interface_get_name(tmp_service_interface);
406                 if (g_strcmp0(service_interface_name, object_name) == 0) {
407                         g_free(object_name);
408
409                         service_interface = tmp_service_interface;
410                         break;
411                 }
412
413                 list = g_slist_next(list);
414         }
415
416         if (NULL == service_interface) {
417                 Z_LOGE("Service interface object of name '%s' not found!",
418                         service_interface_name);
419                 return NULL;
420         }
421
422         Z_LOGD("'%s' found", service_interface_name);
423
424         return service_interface;
425 }
426
427 GHashTable *zblib_service_ref_request_hash_table(ZigBeeService *service)
428 {
429         if (NULL == service) {
430                 Z_LOGE("service is NULL");
431                 return NULL;
432         }
433
434         return service->request_table;
435 }
436
437 gint zblib_service_generate_request_id(ZigBeeService *service)
438 {
439         if (NULL == service) {
440                 Z_LOGE("service is NULL");
441                 return -1;
442         }
443
444         /* Increment request ID */
445         service->request_id++;
446
447         return (gint)service->request_id;
448 }