aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlessio Vanni <vannilla@firemail.cc>2021-04-04 16:51:09 +0200
committerMartin Schanzenbach <mschanzenbach@posteo.de>2021-04-05 18:15:14 +0200
commit45720bde1c56c414fec8a1c3d5775208c3b32139 (patch)
tree74dc74c8d1639c50901320b688bb3cae81d47266 /src
parent879cfdc43babb80a0c0618dfe3afa960fbed6e7d (diff)
downloadgnunet-45720bde1c56c414fec8a1c3d5775208c3b32139.tar.gz
gnunet-45720bde1c56c414fec8a1c3d5775208c3b32139.zip
Implement function to load plugins within a specific context
When `GNUNET_OS_init' is called to change the application project data, lazy-loading plugins will fail as it will not find the requested files. The function will temporarily swap the project data with the argument value and will search for plugins, within the installation directory tree inferred from that structure. Applications can still use `GNUNET_PLUGIN_load_all' to load their plugins from within their own installation directory tree, though services are recommended to use the `in_context' version to avoid falling in the same pit. Signed-off-by: Martin Schanzenbach <mschanzenbach@posteo.de>
Diffstat (limited to 'src')
-rw-r--r--src/block/block.c9
-rw-r--r--src/datacache/datacache.c24
-rw-r--r--src/gnsrecord/gnsrecord.c13
-rw-r--r--src/include/gnunet_plugin_lib.h22
-rw-r--r--src/reclaim/reclaim_attribute.c9
-rw-r--r--src/reclaim/reclaim_credential.c9
-rw-r--r--src/rest/gnunet-rest-server.c9
-rw-r--r--src/util/plugin.c33
8 files changed, 98 insertions, 30 deletions
diff --git a/src/block/block.c b/src/block/block.c
index 5abe64e69..975c0f747 100644
--- a/src/block/block.c
+++ b/src/block/block.c
@@ -134,10 +134,11 @@ GNUNET_BLOCK_context_create (const struct GNUNET_CONFIGURATION_Handle *cfg)
134 134
135 ctx = GNUNET_new (struct GNUNET_BLOCK_Context); 135 ctx = GNUNET_new (struct GNUNET_BLOCK_Context);
136 ctx->cfg = cfg; 136 ctx->cfg = cfg;
137 GNUNET_PLUGIN_load_all ("libgnunet_plugin_block_", 137 GNUNET_PLUGIN_load_all_in_context (GNUNET_OS_project_data_default (),
138 (void *) cfg, 138 "libgnunet_plugin_block_",
139 &add_plugin, 139 (void *) cfg,
140 ctx); 140 &add_plugin,
141 ctx);
141 return ctx; 142 return ctx;
142} 143}
143 144
diff --git a/src/datacache/datacache.c b/src/datacache/datacache.c
index 1ae228b86..5fc5a7481 100644
--- a/src/datacache/datacache.c
+++ b/src/datacache/datacache.c
@@ -138,6 +138,7 @@ GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
138 struct GNUNET_DATACACHE_Handle *ret; 138 struct GNUNET_DATACACHE_Handle *ret;
139 char *libname; 139 char *libname;
140 char *name; 140 char *name;
141 const struct GNUNET_OS_ProjectData *pd;
141 142
142 if (GNUNET_OK != 143 if (GNUNET_OK !=
143 GNUNET_CONFIGURATION_get_value_size (cfg, section, "QUOTA", &quota)) 144 GNUNET_CONFIGURATION_get_value_size (cfg, section, "QUOTA", &quota))
@@ -190,14 +191,25 @@ GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
190 GNUNET_asprintf (&libname, "libgnunet_plugin_datacache_%s", name); 191 GNUNET_asprintf (&libname, "libgnunet_plugin_datacache_%s", name);
191 ret->short_name = name; 192 ret->short_name = name;
192 ret->lib_name = libname; 193 ret->lib_name = libname;
194 /* Load the plugin within GNUnet's default context */
195 pd = GNUNET_OS_project_data_get ();
196 GNUNET_OS_init(GNUNET_OS_project_data_default ());
193 ret->api = GNUNET_PLUGIN_load (libname, &ret->env); 197 ret->api = GNUNET_PLUGIN_load (libname, &ret->env);
194 if (ret->api == NULL) 198 GNUNET_OS_init(pd);
199 if (NULL == ret->api)
195 { 200 {
196 LOG (GNUNET_ERROR_TYPE_ERROR, 201 /* Try to load the plugin within the application's context
197 _ ("Failed to load datacache plugin for `%s'\n"), 202 This normally happens when the application is not GNUnet itself but a
198 name); 203 third party; inside GNUnet this is effectively a double failure. */
199 GNUNET_DATACACHE_destroy (ret); 204 ret->api = GNUNET_PLUGIN_load (libname, &ret->env);
200 return NULL; 205 if (NULL == ret->api)
206 {
207 LOG (GNUNET_ERROR_TYPE_ERROR,
208 _ ("Failed to load datacache plugin for `%s'\n"),
209 name);
210 GNUNET_DATACACHE_destroy (ret);
211 return NULL;
212 }
201 } 213 }
202 return ret; 214 return ret;
203} 215}
diff --git a/src/gnsrecord/gnsrecord.c b/src/gnsrecord/gnsrecord.c
index 8d5a6d95b..31749a629 100644
--- a/src/gnsrecord/gnsrecord.c
+++ b/src/gnsrecord/gnsrecord.c
@@ -102,15 +102,12 @@ init ()
102 if (1 == once) 102 if (1 == once)
103 return; 103 return;
104 once = 1; 104 once = 1;
105 const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
106 const struct GNUNET_OS_ProjectData *dpd = GNUNET_OS_project_data_default ();
107 105
108 if (pd != dpd) 106 GNUNET_PLUGIN_load_all_in_context (GNUNET_OS_project_data_default (),
109 GNUNET_OS_init (dpd); 107 "libgnunet_plugin_gnsrecord_",
110 GNUNET_PLUGIN_load_all ("libgnunet_plugin_gnsrecord_", NULL, 108 NULL,
111 &add_plugin, NULL); 109 &add_plugin,
112 if (pd != dpd) 110 NULL);
113 GNUNET_OS_init (pd);
114} 111}
115 112
116 113
diff --git a/src/include/gnunet_plugin_lib.h b/src/include/gnunet_plugin_lib.h
index ffffcab8b..d265eb343 100644
--- a/src/include/gnunet_plugin_lib.h
+++ b/src/include/gnunet_plugin_lib.h
@@ -122,6 +122,28 @@ GNUNET_PLUGIN_load_all (const char *basename,
122 122
123 123
124/** 124/**
125 * Load all compatible plugins with the given base name while inside the given
126 * context (i.e. a specific project data structure.)
127 *
128 * Note that the library must export symbols called `basename_ANYTHING_init`
129 * and `basename_ANYTHING__done`. These will be called when the library is
130 * loaded and unloaded respectively.
131 *
132 * @param ctx the context used to find the plugins
133 * @param basename basename of the plugins to load
134 * @param arg argument to the plugin initialization function
135 * @param cb function to call for each plugin found
136 * @param cb_cls closure for @a cb
137 */
138void
139GNUNET_PLUGIN_load_all_in_context (const struct GNUNET_OS_ProjectData *ctx,
140 const char *basename,
141 void *arg,
142 GNUNET_PLUGIN_LoaderCallback cb,
143 void *cb_cls);
144
145
146/**
125 * Unload plugin (runs the "done" callback and returns whatever "done" 147 * Unload plugin (runs the "done" callback and returns whatever "done"
126 * returned). The plugin is then unloaded. 148 * returned). The plugin is then unloaded.
127 * 149 *
diff --git a/src/reclaim/reclaim_attribute.c b/src/reclaim/reclaim_attribute.c
index 14690d7c9..21fdd83a2 100644
--- a/src/reclaim/reclaim_attribute.c
+++ b/src/reclaim/reclaim_attribute.c
@@ -96,10 +96,11 @@ init ()
96 if (GNUNET_YES == initialized) 96 if (GNUNET_YES == initialized)
97 return; 97 return;
98 initialized = GNUNET_YES; 98 initialized = GNUNET_YES;
99 GNUNET_PLUGIN_load_all ("libgnunet_plugin_reclaim_attribute_", 99 GNUNET_PLUGIN_load_all_in_context (GNUNET_OS_project_data_default (),
100 NULL, 100 "libgnunet_plugin_reclaim_attribute_",
101 &add_plugin, 101 NULL,
102 NULL); 102 &add_plugin,
103 NULL);
103} 104}
104 105
105/** 106/**
diff --git a/src/reclaim/reclaim_credential.c b/src/reclaim/reclaim_credential.c
index 05601c3d3..c8c0d397c 100644
--- a/src/reclaim/reclaim_credential.c
+++ b/src/reclaim/reclaim_credential.c
@@ -96,10 +96,11 @@ init ()
96 if (GNUNET_YES == initialized) 96 if (GNUNET_YES == initialized)
97 return; 97 return;
98 initialized = GNUNET_YES; 98 initialized = GNUNET_YES;
99 GNUNET_PLUGIN_load_all ("libgnunet_plugin_reclaim_credential_", 99 GNUNET_PLUGIN_load_all_in_context (GNUNET_OS_project_data_default (),
100 NULL, 100 "libgnunet_plugin_reclaim_credential_",
101 &add_plugin, 101 NULL,
102 NULL); 102 &add_plugin,
103 NULL);
103} 104}
104 105
105 106
diff --git a/src/rest/gnunet-rest-server.c b/src/rest/gnunet-rest-server.c
index e6e03b16d..ecb3e2ae5 100644
--- a/src/rest/gnunet-rest-server.c
+++ b/src/rest/gnunet-rest-server.c
@@ -1229,10 +1229,11 @@ run (void *cls,
1229 return; 1229 return;
1230 } 1230 }
1231 /* Load plugins */ 1231 /* Load plugins */
1232 GNUNET_PLUGIN_load_all ("libgnunet_plugin_rest", 1232 GNUNET_PLUGIN_load_all_in_context (GNUNET_OS_project_data_default (),
1233 (void *) cfg, 1233 "libgnunet_plugin_rest",
1234 &load_plugin, 1234 (void *) cfg,
1235 NULL); 1235 &load_plugin,
1236 NULL);
1236 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); 1237 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1237} 1238}
1238 1239
diff --git a/src/util/plugin.c b/src/util/plugin.c
index d169bc911..feb661f24 100644
--- a/src/util/plugin.c
+++ b/src/util/plugin.c
@@ -388,6 +388,11 @@ find_libraries (void *cls,
388 * `basename_ANYTHING_init` and `basename_ANYTHING__done`. These will 388 * `basename_ANYTHING_init` and `basename_ANYTHING__done`. These will
389 * be called when the library is loaded and unloaded respectively. 389 * be called when the library is loaded and unloaded respectively.
390 * 390 *
391 * If you are writing a service to which third-party applications can connect,
392 * like GNUnet's own GNS service for example, you should use
393 * #GNUNET_PLUGIN_load_all_in_context instead of this function, passing your
394 * service's project data as context.
395 *
391 * @param basename basename of the plugins to load 396 * @param basename basename of the plugins to load
392 * @param arg argument to the plugin initialization function 397 * @param arg argument to the plugin initialization function
393 * @param cb function to call for each plugin found 398 * @param cb function to call for each plugin found
@@ -420,4 +425,32 @@ GNUNET_PLUGIN_load_all (const char *basename,
420} 425}
421 426
422 427
428/**
429 * Load all compatible plugins with the given base name while inside the given
430 * context (i.e. a specific project data structure.)
431 *
432 * Note that the library must export symbols called `basename_ANYTHING_init`
433 * and `basename_ANYTHING__done`. These will be called when the library is
434 * loaded and unloaded respectively.
435 *
436 * @param ctx the context used to find the plugins
437 * @param basename basename of the plugins to load
438 * @param arg argument to the plugin initialization function
439 * @param cb function to call for each plugin found
440 * @param cb_cls closure for @a cb
441 */
442void
443GNUNET_PLUGIN_load_all_in_context (const struct GNUNET_OS_ProjectData *ctx,
444 const char *basename,
445 void *arg,
446 GNUNET_PLUGIN_LoaderCallback cb,
447 void *cb_cls)
448{
449 const struct GNUNET_OS_ProjectData *cpd = GNUNET_OS_project_data_get ();
450 GNUNET_OS_init (ctx);
451 GNUNET_PLUGIN_load_all (basename, arg, cb, cb_cls);
452 GNUNET_OS_init (cpd);
453}
454
455
423/* end of plugin.c */ 456/* end of plugin.c */