Switch to a plugin model
authorManuel Bachmann <manuel.bachmann@iot.bzh>
Mon, 21 Dec 2015 05:57:05 +0000 (06:57 +0100)
committerManuel Bachmann <manuel.bachmann@iot.bzh>
Mon, 21 Dec 2015 06:00:46 +0000 (07:00 +0100)
Each API now compiles to a ".so" file, which gets searched
for in the "${libdir}/afb" directory at startup.

We can now load an arbitrary number of plugins (> 10).

Signed-off-by: Manuel Bachmann <manuel.bachmann@iot.bzh>
13 files changed:
CMakeLists.txt
include/proto-def.h
plugins/CMakeLists.txt
plugins/audio/CMakeLists.txt [new file with mode: 0644]
plugins/audio/audio-api.c
plugins/radio/CMakeLists.txt [new file with mode: 0644]
plugins/radio/radio-api.c
plugins/samples/CMakeLists.txt [new file with mode: 0644]
plugins/samples/HelloWorld.c
plugins/samples/SamplePost.c
plugins/session/CMakeLists.txt [new file with mode: 0644]
plugins/session/token-api.c
src/rest-api.c

index a3ab4c3..4fba65e 100644 (file)
@@ -11,6 +11,7 @@ SET(PROJECT_VERSION "0.1")
 INCLUDE(FindPkgConfig)
 INCLUDE(CheckIncludeFiles)
 INCLUDE(CheckLibraryExists)
+INCLUDE(GNUInstallDirs)
 
 CHECK_INCLUDE_FILES(magic.h HAVE_MAGIC_H)
 CHECK_LIBRARY_EXISTS(magic magic_load "" HAVE_LIBMAGIC_SO)
@@ -51,12 +52,16 @@ INCLUDE(FindThreads)
 FIND_PACKAGE(Threads)
 
 SET(include_dirs ${INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/include ${json-c_INCLUDE_DIRS} ${libmicrohttpd_INCLUDE_DIRS} ${uuid_INCLUDE_DIRS} ${alsa_INCLUDE_DIRS} ${librtlsdr_INCLUDE_DIRS})
-SET(link_libraries ${json-c_LIBRARIES} ${libmicrohttpd_LIBRARIES} ${uuid_LIBRARIES} ${alsa_LIBRARIES} ${librtlsdr_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${libefence_LIBRARIES} -lmagic -lm)
+SET(link_libraries ${json-c_LIBRARIES} ${libmicrohttpd_LIBRARIES} ${uuid_LIBRARIES} ${alsa_LIBRARIES} ${librtlsdr_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${libefence_LIBRARIES} -lmagic -lm -ldl)
+SET(plugin_install_dir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/afb)
+
+ADD_DEFINITIONS(-DPLUGIN_INSTALL_DIR="${plugin_install_dir}")
 
 ADD_SUBDIRECTORY(src)
 ADD_SUBDIRECTORY(plugins)
 
-ADD_EXECUTABLE(afb-daemon $<TARGET_OBJECTS:src> $<TARGET_OBJECTS:plugins>)
+ADD_EXECUTABLE(afb-daemon $<TARGET_OBJECTS:src>)
+INCLUDE_DIRECTORIES(${include_dirs})
 TARGET_LINK_LIBRARIES(afb-daemon ${link_libraries})
 
 INSTALL(TARGETS afb-daemon
index 315cecf..937d693 100644 (file)
@@ -34,11 +34,7 @@ PUBLIC AFB_PostHandle* getPostHandle (AFB_request *request);
 void initPlugins (AFB_session *session);
 
 typedef AFB_plugin* (*AFB_pluginCB)();
-PUBLIC  AFB_plugin* tokenRegister ();
-PUBLIC  AFB_plugin* audioRegister ();
-PUBLIC  AFB_plugin* helloWorldRegister ();
-PUBLIC  AFB_plugin* radioRegister ();
-PUBLIC  AFB_plugin* samplePostRegister ();
+PUBLIC  AFB_plugin* pluginRegister ();
 
 // Session handling
 PUBLIC AFB_error sessionCheckdir     (AFB_session *session);
index 7e3e080..c66de5e 100644 (file)
@@ -1,14 +1,4 @@
-SET(SESSION_PLUGIN session/token-api.c)
-SET(HELLOWORLD_PLUGINS samples/HelloWorld.c)
-SET(SAMPLEPOST_PLUGINS samples/SamplePost.c)
-IF(alsa_FOUND)
-  SET(AUDIO_PLUGIN audio/audio-api.c audio/audio-alsa.c)
-ENDIF(alsa_FOUND)
-IF(librtlsdr_FOUND)
-  SET(RADIO_PLUGIN radio/radio-api.c radio/radio-rtlsdr.c)
-ENDIF(librtlsdr_FOUND)
-
-SET(PLUGINS_SOURCES ${SESSION_PLUGIN} ${HELLOWORLD_PLUGINS} ${SAMPLEPOST_PLUGINS} ${AUDIO_PLUGIN} ${RADIO_PLUGIN})
-
-ADD_LIBRARY(plugins OBJECT ${PLUGINS_SOURCES})
-INCLUDE_DIRECTORIES(${include_dirs})
+ADD_SUBDIRECTORY(session)
+ADD_SUBDIRECTORY(samples)
+ADD_SUBDIRECTORY(audio)
+ADD_SUBDIRECTORY(radio)
diff --git a/plugins/audio/CMakeLists.txt b/plugins/audio/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b5adc64
--- /dev/null
@@ -0,0 +1,10 @@
+IF(alsa_FOUND)
+
+  INCLUDE_DIRECTORIES(${include_dirs})
+
+  ADD_LIBRARY(audio-api MODULE audio-api.c audio-alsa.c)
+  SET_TARGET_PROPERTIES(audio-api PROPERTIES PREFIX "")
+  INSTALL(TARGETS audio-api
+          LIBRARY DESTINATION ${plugin_install_dir})
+
+ENDIF(alsa_FOUND)
index 53a4bea..60a5a96 100644 (file)
@@ -223,7 +223,7 @@ STATIC AFB_restapi pluginApis[]= {
   {NULL}
 };
 
-PUBLIC AFB_plugin *audioRegister () {
+PUBLIC AFB_plugin *pluginRegister () {
     AFB_plugin *plugin = malloc (sizeof(AFB_plugin));
     plugin->type   = AFB_PLUGIN_JSON;
     plugin->info   = "Application Framework Binder - Audio plugin";
diff --git a/plugins/radio/CMakeLists.txt b/plugins/radio/CMakeLists.txt
new file mode 100644 (file)
index 0000000..c7c8541
--- /dev/null
@@ -0,0 +1,10 @@
+IF(librtlsdr_FOUND)
+
+  INCLUDE_DIRECTORIES(${include_dirs})
+
+  ADD_LIBRARY(radio-api MODULE radio-api.c radio-rtlsdr.c)
+  SET_TARGET_PROPERTIES(radio-api PROPERTIES PREFIX "")
+  INSTALL(TARGETS radio-api
+          LIBRARY DESTINATION ${plugin_install_dir})
+
+ENDIF(librtlsdr_FOUND)
index 3de8e04..cfa2599 100644 (file)
@@ -327,7 +327,7 @@ STATIC AFB_restapi pluginApis[]= {
   {NULL}
 };
 
-PUBLIC AFB_plugin* radioRegister () {
+PUBLIC AFB_plugin* pluginRegister () {
     AFB_plugin *plugin = malloc (sizeof(AFB_plugin));
     plugin->type  = AFB_PLUGIN_JSON;
     plugin->info  = "Application Framework Binder - Radio plugin";
diff --git a/plugins/samples/CMakeLists.txt b/plugins/samples/CMakeLists.txt
new file mode 100644 (file)
index 0000000..ef5b449
--- /dev/null
@@ -0,0 +1,11 @@
+INCLUDE_DIRECTORIES(${include_dirs})
+
+ADD_LIBRARY(helloWorld-api MODULE HelloWorld.c)
+SET_TARGET_PROPERTIES(helloWorld-api PROPERTIES PREFIX "")
+INSTALL(TARGETS helloWorld-api
+        LIBRARY DESTINATION ${plugin_install_dir})
+
+ADD_LIBRARY(samplePost-api MODULE SamplePost.c)
+SET_TARGET_PROPERTIES(samplePost-api PROPERTIES PREFIX "")
+INSTALL(TARGETS samplePost-api
+        LIBRARY DESTINATION ${plugin_install_dir})
index 4117c26..5638b42 100644 (file)
@@ -84,11 +84,11 @@ STATIC  AFB_restapi pluginApis[]= {
 };
 
 
-PUBLIC AFB_plugin *helloWorldRegister () {
+PUBLIC AFB_plugin *pluginRegister () {
     AFB_plugin *plugin = malloc (sizeof (AFB_plugin));
     plugin->type  = AFB_PLUGIN_JSON;
     plugin->info  = "Application Framework Binder Service";
     plugin->prefix= "dbus";        
     plugin->apis  = pluginApis;
     return (plugin);
-};
\ No newline at end of file
+};
index 8548501..223f74e 100644 (file)
@@ -165,7 +165,7 @@ STATIC  AFB_restapi pluginApis[]= {
   {NULL}
 };
 
-PUBLIC AFB_plugin *samplePostRegister () {
+PUBLIC AFB_plugin *pluginRegister () {
     AFB_plugin *plugin = malloc (sizeof (AFB_plugin));
     plugin->type  = AFB_PLUGIN_JSON; 
     plugin->info  = "Application Framework Binder Service";
@@ -174,4 +174,4 @@ PUBLIC AFB_plugin *samplePostRegister () {
     plugin->handle= (void*) "What ever you want";
     
     return (plugin);
-};
\ No newline at end of file
+};
diff --git a/plugins/session/CMakeLists.txt b/plugins/session/CMakeLists.txt
new file mode 100644 (file)
index 0000000..ddd185d
--- /dev/null
@@ -0,0 +1,6 @@
+INCLUDE_DIRECTORIES(${include_dirs})
+
+ADD_LIBRARY(token-api MODULE token-api.c)
+SET_TARGET_PROPERTIES(token-api PROPERTIES PREFIX "")
+INSTALL(TARGETS token-api
+        LIBRARY DESTINATION ${plugin_install_dir})
index b6ebb8a..ba6d276 100644 (file)
@@ -94,7 +94,7 @@ STATIC  AFB_restapi pluginApis[]= {
   {NULL}
 };
 
-PUBLIC AFB_plugin *tokenRegister () {
+PUBLIC AFB_plugin *pluginRegister () {
     AFB_plugin *plugin = malloc (sizeof (AFB_plugin));
     plugin->type  = AFB_PLUGIN_JSON; 
     plugin->info  = "Application Framework Binder Service";
@@ -104,4 +104,4 @@ PUBLIC AFB_plugin *tokenRegister () {
     plugin->freeCtxCB= (void*) clientContextFree;
     
     return (plugin);
-};
\ No newline at end of file
+};
index 1635d44..da33167 100644 (file)
@@ -22,6 +22,8 @@
 
 #include "../include/local-def.h"
 
+#include <dirent.h>
+#include <dlfcn.h>
 #include <setjmp.h>
 #include <signal.h>
 
@@ -629,20 +631,46 @@ STATIC AFB_plugin ** RegisterJsonPlugins(AFB_plugin **plugins) {
 }
 
 void initPlugins(AFB_session *session) {
-    static AFB_plugin * plugins[10];
+    static AFB_plugin **plugins;
+    AFB_plugin* (*pluginRegisterFct)(void);
+    void *plugin;
+    char *pluginPath;
+    struct dirent *pluginDir;
+    DIR *dir;
     afbJsonType = json_object_new_string (AFB_MSG_JTYPE);
     int i = 0;
 
-    plugins[i++] = tokenRegister(session);
-    plugins[i++] = helloWorldRegister(session);
-    plugins[i++] = samplePostRegister(session);
-#ifdef HAVE_AUDIO_PLUGIN
-    plugins[i++] = audioRegister(session);
-#endif
-#ifdef HAVE_RADIO_PLUGIN
-    plugins[i++] = radioRegister(session),
-#endif
+    if ((dir = opendir(PLUGIN_INSTALL_DIR)) == NULL) {
+        fprintf(stderr, "Could not open plugin directory=%s\n", PLUGIN_INSTALL_DIR);
+        return;
+    }
+
+    while ((pluginDir = readdir(dir)) != NULL) {
+
+        if (!strstr (pluginDir->d_name, ".so"))
+            continue;
+
+        asprintf (&pluginPath, PLUGIN_INSTALL_DIR "/%s", pluginDir->d_name);
+        plugin = dlopen (pluginPath, RTLD_NOW | RTLD_LOCAL);
+        pluginRegisterFct = dlsym (plugin, "pluginRegister");
+        free (pluginPath);
+        if (!plugin) {
+            if (verbose) fprintf(stderr, "[%s] is not a binary plugin, continuing...\n", pluginDir->d_name);
+            continue;
+        } else if (!pluginRegisterFct) {
+            if (verbose) fprintf(stderr, "[%s] is not an AFB plugin, continuing...\n", pluginDir->d_name);
+            continue;
+        }
+
+        if (verbose) fprintf(stderr, "[%s] is a valid AFB plugin, loading it\n", pluginDir->d_name);
+        plugins = (AFB_plugin **) realloc (plugins, (i+1)*sizeof(AFB_plugin));
+        plugins[i] = (AFB_plugin *) malloc (sizeof(AFB_plugin));
+        plugins[i] = (**pluginRegisterFct)();
+        i++;
+    }
     plugins[i++] = NULL;
+
+    closedir (dir);
     
     // complete plugins and save them within current sessions    
     session->plugins = RegisterJsonPlugins(plugins);