|
1 #ifndef MODULE_H |
|
2 #define MODULE_H |
|
3 |
|
4 /** |
|
5 * @file |
|
6 * |
|
7 * Dynamically loadable modules for use with nexus. |
|
8 * |
|
9 * The modules are loaded using dlopen(), and hence should be standard dynamic libraries. Modules are then "loaded" by |
|
10 * resolving a `struct module_funcs` symbol called "<modname>_funcs", and then using the init func to construct a |
|
11 * "context", which is then further manipulated by various other module functions. |
|
12 * |
|
13 * Modules are also reference counted, mainly for implementing module_unload(). When a module is first loaded, it has |
|
14 * a reference count of one - the entry in struct modules. Later, modules can be referenced using module_get(), and |
|
15 * returned with module_put() once done. The module should never be destroyed during its lifetime, until a |
|
16 * module_unload() occurs. At this point, the module is removed from the modules_list, and the one reference is |
|
17 * 'passed on' to the module itself. Once it has finished unloading, it can call module_unloaded() on the reference it was |
|
18 * given by module_desc::unload, which may then result in a deferred module_destroy(). |
|
19 * |
|
20 * Module destroying itself is an interesting issue, since modules effectively need to be able to destroy themselves |
|
21 * (as they must be able to perform cleanup, and then notify completion from inside an event loop callback). This means |
|
22 * that they cannot directly execute a module_destroy() on themselves - if we call dlclose() with dlopen-mapped code |
|
23 * pages on the stack, a segfault ensues. Hence, they must call module_unloaded() on themselves, which then executes a |
|
24 * deferred module_destroy() if there are no references left. Otherwise, the module should be safe from external code, |
|
25 * as module_put() should never cause a module to be destroyed before module_unloaded() is executed, due to the primary |
|
26 * reference. |
|
27 * |
|
28 * Ugh, it's compliated, I need to write a clearer explenation once it's implemented :) |
|
29 */ |
|
30 |
|
31 struct module; |
|
32 |
|
33 #include "nexus.h" |
|
34 #include "config.h" |
|
35 #include <lib/error.h> |
|
36 |
|
37 #include <sys/queue.h> |
|
38 #include <stdbool.h> |
|
39 |
|
40 enum module_error_code { |
|
41 ERR_MODULE_NONE, |
|
42 ERR_MODULE_NAME, ///< invalid module_info.name |
|
43 ERR_MODULE_DUP, ///< module already opened |
|
44 ERR_MODULE_PATH, ///< resolving the path failed |
|
45 ERR_MODULE_OPEN, ///< dlopen() failed |
|
46 ERR_MODULE_SYM, ///< invalid symbol |
|
47 ERR_MODULE_INIT_FUNC, ///< invalid module_init_func_t |
|
48 ERR_MODULE_CONF, ///< value error in configuration data |
|
49 ERR_MODULE_STATE, ///< module in wrong state for operation |
|
50 }; |
|
51 |
|
52 const struct error_list module_errors; |
|
53 |
|
54 /** |
|
55 * Information required to load/identify a module. |
|
56 */ |
|
57 struct module_info { |
|
58 /** Human-readable name */ |
|
59 const char *name; |
|
60 |
|
61 /** Filesystem path to the .so */ |
|
62 const char *path; |
|
63 }; |
|
64 |
|
65 /** |
|
66 * A table of (function/other) pointers defining a module's behaviour. This is dynamically resolved from the module DSO |
|
67 * using the "<mod_name>_module" symbol. |
|
68 */ |
|
69 struct module_desc { |
|
70 /** |
|
71 * Initialize the module, returning an opaque context pointer that is stored in the module state, and supplied for |
|
72 * subsequent calls. The supplied nexus arg can be used to access the global state. |
|
73 * |
|
74 * Implementing this is mandatory. |
|
75 * |
|
76 * @param nexus a pointer to the nexus struct containing the global state |
|
77 * @param ctx_ptr the context pointer should be returned via this |
|
78 * @param err returned error info |
|
79 */ |
|
80 err_t (*init) (struct nexus *nexus, void **ctx_ptr, error_t *err); |
|
81 |
|
82 /** |
|
83 * A module may define a set of available configuration parameters for use by module_conf, by setting this to an |
|
84 * array of config_option's. |
|
85 * |
|
86 * The handler functions will recieve the module's context pointer as their ctx argument. |
|
87 * |
|
88 * Implementing this is optional, but recommended. |
|
89 */ |
|
90 const struct config_option *config_options; |
|
91 |
|
92 /** |
|
93 * Unload the module, removing all handlers/callbacks added to the nexus' irc_client. This does not have to act |
|
94 * immediately, and will still have access to all irc_* resources it had earlier, and may perform I/O to unload |
|
95 * cleanly. But the unloading should complete reasonably quickly, after which all event handlers added by the |
|
96 * module to the nexus' ev_base should have been removed, and resources released. |
|
97 * |
|
98 * The module given as an argument is the module itself - which has been removed from the modules_list - the |
|
99 * primary reference is passed on to the module. Once the module has finished unloading, it may call module_put(), |
|
100 * which may then call module_destroy(), if no other references were left. |
|
101 * |
|
102 * If the unload operation fails (returns an error code), then the module is considered as unloaded (as if |
|
103 * module_unloaded() was called - don't call this if you return an error). |
|
104 * |
|
105 * Implementing this is optional, if all of this can be implemented in destroy. |
|
106 * |
|
107 * @param ctx the module's context pointer as returned by init |
|
108 * @param module the hanging module reference, that must be passed to module_unloaded() |
|
109 * @return error code |
|
110 */ |
|
111 err_t (*unload) (void *ctx, struct module *module); |
|
112 |
|
113 /** |
|
114 * Destroy the module now. No later chances, the module's code will be unloaded directly after this, which means |
|
115 * that attempts to execute the module's code (even on the stack...) after this will segfault. |
|
116 * |
|
117 * The module code /should/ garuntee that this is never called from *inside* the module code - calls to |
|
118 * module_destroy() will be deferred via the event loop if needed. |
|
119 * |
|
120 * Implementing this is optional. |
|
121 */ |
|
122 void (*destroy) (void *ctx); |
|
123 }; |
|
124 |
|
125 /** |
|
126 * A loaded module. |
|
127 */ |
|
128 struct module { |
|
129 /** The identifying info for the module */ |
|
130 struct module_info info; |
|
131 |
|
132 /** Possible dynamically allocated path */ |
|
133 char *path_buf; |
|
134 |
|
135 /** The dlopen handle */ |
|
136 void *handle; |
|
137 |
|
138 /** The module entry point */ |
|
139 struct module_desc *desc; |
|
140 |
|
141 /** The module context object */ |
|
142 void *ctx; |
|
143 |
|
144 /** Reference back to modules struct used to load this module */ |
|
145 struct modules *modules; |
|
146 |
|
147 /** Reference count for destroy() */ |
|
148 size_t refcount; |
|
149 |
|
150 /** Is the module currently being unloaded? */ |
|
151 bool unloading; |
|
152 |
|
153 /** Our entry in the list of modules */ |
|
154 TAILQ_ENTRY(module) modules_list; |
|
155 }; |
|
156 |
|
157 /** |
|
158 * A set of loaded modules, and functionality to load more |
|
159 */ |
|
160 struct modules { |
|
161 /** The nexus in use */ |
|
162 struct nexus *nexus; |
|
163 |
|
164 /** Module search path */ |
|
165 const char *path; |
|
166 |
|
167 /** List of loaded modules */ |
|
168 TAILQ_HEAD(module_ctx_modules, module) list; |
|
169 }; |
|
170 |
|
171 |
|
172 /** |
|
173 * Maximum length of a module name |
|
174 */ |
|
175 #define MODULE_NAME_MAX 24 |
|
176 |
|
177 /** |
|
178 * Maximum length of module symbol suffix |
|
179 */ |
|
180 #define MODULE_SUFFIX_MAX 16 |
|
181 |
|
182 /** |
|
183 * Maximum length of symbol name name, including terminating NUL |
|
184 */ |
|
185 #define MODULE_SYMBOL_MAX (MODULE_NAME_MAX + 1 + MODULE_SUFFIX_MAX + 1) |
|
186 |
|
187 /** |
|
188 * Create a new modules state |
|
189 */ |
|
190 err_t modules_create (struct modules **modules_ptr, struct nexus *nexus); |
|
191 |
|
192 /** |
|
193 * Set a search path for finding modules by name. The given string won't be copied. |
|
194 * |
|
195 * A module called "<name>" will be searched for at "<path>/mod_<name>.so" |
|
196 * |
|
197 * If path is NULL, this doesn't change anything. This returns the old path, which may be NULL. |
|
198 * |
|
199 * @param modules the modules state |
|
200 * @param path the new search path, or NULL to just get the old one |
|
201 * @return the old search path |
|
202 */ |
|
203 const char* modules_path (struct modules *modules, const char *path); |
|
204 |
|
205 /** |
|
206 * Get a reference to the module, which must be returned using module_put |
|
207 * |
|
208 * @param modules the modules state |
|
209 * @param name the module name to get |
|
210 * @return the module struct, or NULL if not found |
|
211 */ |
|
212 struct module* modules_get (struct modules *modules, const char *name); |
|
213 |
|
214 /** |
|
215 * Unload all modules, this just calls module_unload for each module, logging errors as warnings. |
|
216 */ |
|
217 err_t modules_unload (struct modules *modules); |
|
218 |
|
219 /** |
|
220 * Destroy all modules immediately. |
|
221 */ |
|
222 void modules_destroy (struct modules *modules); |
|
223 |
|
224 |
|
225 |
|
226 /*******************************************/ |
|
227 |
|
228 |
|
229 /** |
|
230 * Return a module's name |
|
231 */ |
|
232 const char* module_name (struct module *module); |
|
233 |
|
234 /** |
|
235 * Load a new module, as named by info. |
|
236 * |
|
237 * If info->path is not given, the module will be searched for using the path set by modules_path(). |
|
238 * |
|
239 * If module_ptr is given, a reference (that must be module_put'd) is returned, that must be returned using |
|
240 * module_put(). |
|
241 * |
|
242 * @param modules the module-loading context |
|
243 * @param module_ptr retuturned new module struct, as a new reference, if not NULL. |
|
244 * @param info the info required to identify and load the module |
|
245 * @param err returned error info |
|
246 */ |
|
247 err_t module_load (struct modules *modules, struct module **module_ptr, const struct module_info *info, error_t *err); |
|
248 |
|
249 /** |
|
250 * Return a module retrieved using module_get |
|
251 */ |
|
252 void module_put (struct module *module); |
|
253 |
|
254 /** |
|
255 * Look up a module configuration option by name |
|
256 */ |
|
257 const struct config_option* module_conf_lookup (struct module *module, const char *name, error_t *err); |
|
258 |
|
259 /** |
|
260 * Apply a module configuration option using a structured value |
|
261 */ |
|
262 err_t module_conf (struct module *module, const struct config_option *opt, const struct config_value *value, error_t *err); |
|
263 |
|
264 /** |
|
265 * Set a module configuration option using a raw value |
|
266 */ |
|
267 err_t module_conf_raw (struct module *module, const char *name, char *value, error_t *err); |
|
268 |
|
269 /** |
|
270 * Unload a module. This removes the module from the modules_list, marks it as unloading, and then calls the module's |
|
271 * \p unload function, passing it the primary reference. The module's unload code will then go about shutting down the |
|
272 * module, and once that is done, it may module_put() the primary reference, which may then lead to module_destroy(). |
|
273 * |
|
274 * This returns ERR_MODULE_STATE if the module is already being unloaded, or other errors from the module's own unload |
|
275 * functionality. |
|
276 */ |
|
277 err_t module_unload (struct module *module); |
|
278 |
|
279 /** |
|
280 * Used by a module itself to indicate that an module_desc::unload() operation has completed. This will execute a |
|
281 * deferred module_destroy() if there are no more references left on the module. |
|
282 * |
|
283 * Note: this is not intended to be called from outside the given module itself... |
|
284 */ |
|
285 void module_unloaded (struct module *module); |
|
286 |
|
287 /** |
|
288 * Destroy a module, releasing as many resources as possible, but not stopping for errors. |
|
289 * |
|
290 * This does not enforce the correct refcount - 'tis the caller's responsibility. Prints out a warning if |
|
291 * refcount > 0. |
|
292 */ |
|
293 void module_destroy (struct module *module); |
|
294 |
|
295 #endif |