/ story-4-Plugins.org
story-4-Plugins.org
1 #+TITLE: Story 4 - Plugins 2 #+OPTIONS: author:nil date:nil 3 4 Plugins are a collection of code that plugs into the Le'Sec Core library to 5 perform certain types of functions. Plugins may be built into the 6 application that uses the Le'Sec Core library, any other library the 7 application is linked with, or as a shared object that's loaded 8 dynamically. 9 10 * Start and stop functions 11 12 By definition, a Le'Sec plugin is nothing more than a start and a stop 13 function, both taking the exact same argument. 14 15 #+BEGIN_SRC C 16 LE_STATUS start(LSC_plugin_t *plugin); 17 LE_STATUS stop(LSC_plugin_t *plugin); 18 #+END_SRC 19 20 The ~start()~ and ~stop()~ names are only figurative, they could be named 21 anything anyone wishes. 22 23 ~plugin~ is explained further down. 24 25 For convenience, the function signature types ~LSC_plugin_start_fn~ and 26 ~LSC_plugin_stop_fn~ should be defined. 27 28 * Plugin invocation and revocation 29 30 Applications will need to get a plugin started (invocation) and stopped 31 (revocation), for which there should be simple API. 32 33 #+BEGIN_SRC C 34 LE_STATUS LSC_invoke_plugin(LSC_plugin_start_fn *start, LSC_plugin_t **plugin, 35 LSC_env_t *env); 36 LE_STATUS LSC_revoke_plugin(LSC_plugin_stop_fn *stop, LSC_plugin_t *plugin); 37 #+END_SRC 38 39 ~LSC_invoke_plugin()~ will create and populate an ~LSC_plugin_t~, pass that to 40 the ~start()~ function, as well as assign it to ~*plugin~. The application 41 must pass that same value to ~LSC_revoke_plugin()~ when done with that 42 plugin. 43 44 ~LSC_revoke_plugin()~ will pass ~plugin~ to the ~stop()~ function, and then 45 destroy it. 46 47 * ~LSC_plugin_t~ and manipulating it 48 49 ~LSC_plugin_t~ is most of all a handle type, but it also contains data that's 50 of interest for the plugin itself, as it will want to: 51 52 1. Have some private data held for its life time. 53 2. Have acccess to the parent (application) environment it was called 54 within. 55 56 #+BEGIN_SRC C 57 LE_STATUS LSC_set_plugin_data(LSC_plugin_t *plugin, void *data); 58 LE_STATUS LSC_get_plugin_data(LSC_plugin_t *plugin, void **data); 59 LE_STATUS LSC_get_plugin_parent_environment(LSC_plugin_t *plugin, 60 LSC_env_t **parent_env); 61 #+END_SRC 62 63 * Conventions 64 65 An application is free to specify a plugin start and stop function in 66 whatever manner it wishes. Le'Sec core offers no enforcement with regards 67 to names, or how the application gets access to those functions. 68 69 For dynamically loadable plugins, some conventions are still suitable allow 70 consistency. 71 72 ** Dynamically loadable plugin start and stop function names 73 74 #+BEGIN_SRC C 75 LSC_EXPORT LE_STATUS LSC_plugin_start(LSC_env_t *env) 76 { 77 /* Do stuff */ 78 } 79 80 LSC_EXPORT LE_STATUS LSC_plugin_stop(LSC_env_t *env) 81 { 82 /* Do stuff */ 83 } 84 #+END_SRC 85 86 For convenience, =<lscore/plugin.h>= should declare the functions 87 ~LSC_plugin_start()~ and ~LSC_plugin_stop()~. 88 89 ** Standard location for plugins 90 91 For convenience, =<lscore/plugin.h>= should define a macro with the standard 92 location for Le'Sec plugins. 93 94 #+BEGIN_SRC C 95 #define LSC_PLUGIN_DIR "/usr/share/LeSec/plugins" 96 #+END_SRC 97 98 * Examples 99 100 ** A dynamically loadable plugin 101 102 In a dynamically loadable plugin, the source for the start and stop 103 functions would typically look like this: 104 105 #+BEGIN_SRC C 106 #include <lscore/plugin.h> 107 108 LE_STATUS LSC_plugin_start(LSC_env_t *env) 109 { 110 /* Do stuff */ 111 } 112 113 LE_STATUS LSC_plugin_stop(LSC_env_t *env) 114 { 115 /* Do stuff */ 116 } 117 #+END_SRC 118 119 ** An application loading a plugin 120 121 #+BEGIN_SRC C 122 #include <inttypes.h> 123 #include <dlfcn.h> 124 #include <lscore/plugin.h> 125 126 #define _(x) #x 127 int main(int argc, const char *argv[]) 128 { 129 const char *plugin_name = LSC_PLUGIN_DIR "/foo.so"; 130 void *plugin; 131 LSC_plugin_start_fn *start; 132 LSC_plugin_stop_fn *stop; 133 LSC_env_t *env; 134 LSC_plugin_t *plugin; 135 LE_STATUS sts; 136 137 if ((plugin = dlopen(plugin_name, RTLD_NOW)) != NULL 138 && (start = dlsym(plugin, _(LSC_plugin_start))) != NULL 139 && (stop = dlsym(plugin, _(LSC_plugin_stop))) != NULL 140 && LE_status_is_OK(sts = LSC_new_environment(&env))) { 141 if (!LE_status_is_OK(sts = LE_invoke_plugin(start, &plugin, env))) 142 fprintf(stderr, "Couldn't start %s: %" PRIu32 "\n", 143 plugin_name, sts); 144 if (!LE_status_is_OK(sts = LSC_revoke_plugin(stop, plugin))) 145 fprintf(stderr, "Couldn't stop %s: %" PRIu32 "\n", 146 plugin_name, sts); 147 } 148 } 149 #+END_SRC