2 * Copyright (C) 2016 "IoT.bzh"
3 * Author "Fulup Ar Foll"
4 * Author José Bollo <jose.bollo@iot.bzh>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 * Contain all generic part to handle REST/API
21 * https://www.gnu.org/software/libmicrohttpd/tutorial.html [search 'largepost.c']
32 #include <sys/types.h>
35 #include "../include/local-def.h"
37 #include "afb-plugins.h"
39 static const char plugin_register_function[] = "pluginRegister";
41 AFB_plugin *afb_plugins_search(AFB_session *session, const char *prefix, size_t length)
44 AFB_plugin **plugins, *p;
47 length = strlen(prefix);
49 n = session->config->pluginCount;
50 plugins = session->plugins;
52 for (i = 0 ; i < n ; i++) {
54 if (p->prefixlen == length && !strcmp(p->prefix, prefix))
60 int afb_plugins_add_plugin(AFB_session *session, const char *path)
62 AFB_plugin *desc, *check, **plugins;
63 AFB_plugin *(*pluginRegisterFct) (void);
67 // This is a loadable library let's check if it's a plugin
68 handle = dlopen(path, RTLD_NOW | RTLD_LOCAL);
70 fprintf(stderr, "[%s] not loadable, continuing...\n", path);
74 /* retrieves the register function */
75 pluginRegisterFct = dlsym(handle, plugin_register_function);
76 if (!pluginRegisterFct) {
77 fprintf(stderr, "[%s] not an AFB plugin, continuing...\n", path);
81 fprintf(stderr, "[%s] is a valid AFB plugin\n", path);
83 /* allocates enough memory */
84 plugins = realloc(session->plugins, ((unsigned)session->config->pluginCount + 2) * sizeof(AFB_plugin*));
85 if (plugins == NULL) {
86 fprintf(stderr, "ERROR: plugin [%s] memory missing. continuing...\n", path);
89 session->plugins = plugins;
92 desc = pluginRegisterFct();
94 fprintf(stderr, "ERROR: plugin [%s] register function failed. continuing...\n", path);
98 /* check the returned structure */
99 if (desc->type != AFB_PLUGIN_JSON) {
100 fprintf(stderr, "ERROR: plugin [%s] invalid type %d...\n", path, desc->type);
103 if (desc->prefix == NULL || *desc->prefix == 0) {
104 fprintf(stderr, "ERROR: plugin [%s] bad prefix...\n", path);
107 if (desc->info == NULL || *desc->info == 0) {
108 fprintf(stderr, "ERROR: plugin [%s] bad description...\n", path);
111 if (desc->apis == NULL) {
112 fprintf(stderr, "ERROR: plugin [%s] no APIs...\n", path);
116 /* check previously existing plugin */
117 len = strlen(desc->prefix);
118 check = afb_plugins_search(session, desc->prefix, len);
120 fprintf(stderr, "ERROR: plugin [%s] prefix %s duplicated...\n", path, desc->prefix);
124 /* Prebuild plugin jtype to boost API response */
125 desc->jtype = json_object_new_string(desc->prefix);
126 desc->prefixlen = len;
128 /* record the plugin */
129 session->plugins[session->config->pluginCount] = desc;
130 session->plugins[++session->config->pluginCount] = NULL;
133 fprintf(stderr, "Loading plugin[%d] prefix=[%s] info=%s\n", session->config->pluginCount, desc->prefix, desc->info);
143 static int adddirs(AFB_session * session, char path[PATH_MAX], size_t end)
147 struct dirent ent, *result;
150 /* open the DIR now */
153 fprintf(stderr, "ERROR in scanning plugin directory %s, %m\n", path);
157 fprintf(stderr, "Scanning dir=[%s] for plugins\n", path);
159 /* scan each entry */
163 readdir_r(dir, &ent, &result);
167 len = strlen(ent.d_name);
168 if (len + end >= PATH_MAX) {
169 fprintf(stderr, "path too long for %s\n", ent.d_name);
172 memcpy(&path[end], ent.d_name, len+1);
173 if (ent.d_type == DT_DIR) {
174 /* case of directories */
175 if (ent.d_name[0] == '.') {
178 if (ent.d_name[1] == '.' && len == 2)
181 rc = adddirs(session, path, end+len);;
182 } else if (ent.d_type == DT_REG) {
184 if (!strstr(ent.d_name, ".so"))
186 rc = afb_plugins_add_plugin(session, path);
193 int afb_plugins_add_directory(AFB_session * session, const char *path)
196 char buffer[PATH_MAX];
198 length = strlen(path);
199 if (length >= sizeof(buffer)) {
200 fprintf(stderr, "path too long %lu [%.99s...]\n", (unsigned long)length, path);
204 memcpy(buffer, path, length + 1);
205 return adddirs(session, buffer, length);
208 int afb_plugins_add_path(AFB_session * session, const char *path)
213 rc = stat(path, &st);
215 fprintf(stderr, "Invalid plugin path [%s]: %m\n", path);
216 else if (S_ISDIR(st.st_mode))
217 rc = afb_plugins_add_directory(session, path);
219 rc = afb_plugins_add_plugin(session, path);
223 int afb_plugins_add_pathset(AFB_session * session, const char *pathset)
225 static char sep[] = ":";
229 ps = strdupa(pathset);
231 p = strsep(&ps, sep);
234 rc = afb_plugins_add_path(session, p);
238 void initPlugins(AFB_session * session)
240 int rc = afb_plugins_add_pathset(session, session->config->ldpaths);