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