dumb increment, mirror and status protocol plugins are provided as examples.
+Additional plugin search paths
+------------------------------
+
+Packages that have their own lws plugins can install them in their own
+preferred dir and ask lwsws to scan there by using a config fragment
+like this, in its own conf.d/ file managed by the other package
+
+{
+ "global": {
+ "plugin-dir": "/usr/local/share/coherent-timeline/plugins"
+ }
+}
+
lws-server-status plugin
------------------------
#if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0)
LWS_VISIBLE int
-lws_plat_plugins_init(struct lws_context * context, const char *d)
+lws_plat_plugins_init(struct lws_context * context, const char * const *d)
{
struct lws_plugin_capability lcaps;
struct lws_plugin *plugin;
uv_loop_init(&loop);
- if (!uv_fs_scandir(&loop, &req, d, 0, NULL)) {
- lwsl_err("Scandir on %s failed\n", d);
- return 1;
- }
-
lwsl_notice(" Plugins:\n");
- while (uv_fs_scandir_next(&req, &dent) != UV_EOF) {
- if (strlen(dent.name) < 7)
- continue;
-
- lwsl_notice(" %s\n", dent.name);
+ while (d && *d) {
- snprintf(path, sizeof(path) - 1, "%s/%s", d, dent.name);
- if (uv_dlopen(path, &lib)) {
- uv_dlerror(&lib);
- lwsl_err("Error loading DSO: %s\n", lib.errmsg);
- goto bail;
- }
- /* we could open it, can we get his init function? */
- m = snprintf(path, sizeof(path) - 1, "init_%s",
- dent.name + 3 /* snip lib... */);
- path[m - 3] = '\0'; /* snip the .so */
- if (uv_dlsym(&lib, path, &v)) {
- uv_dlerror(&lib);
- lwsl_err("Failed to get init on %s: %s",
- dent.name, lib.errmsg);
- goto bail;
- }
- initfunc = (lws_plugin_init_func)v;
- lcaps.api_magic = LWS_PLUGIN_API_MAGIC;
- m = initfunc(context, &lcaps);
- if (m) {
- lwsl_err("Initializing %s failed %d\n", dent.name, m);
- goto skip;
+ lwsl_notice(" Scanning %s\n", *d);
+ m =uv_fs_scandir(&loop, &req, *d, 0, NULL);
+ if (m < 1) {
+ lwsl_err("Scandir on %s failed\n", *d);
+ return 1;
}
- plugin = lws_malloc(sizeof(*plugin));
- if (!plugin) {
- lwsl_err("OOM\n");
- goto bail;
- }
- plugin->list = context->plugin_list;
- context->plugin_list = plugin;
- strncpy(plugin->name, dent.name, sizeof(plugin->name) - 1);
- plugin->name[sizeof(plugin->name) - 1] = '\0';
- plugin->lib = lib;
- plugin->caps = lcaps;
- context->plugin_protocol_count += lcaps.count_protocols;
- context->plugin_extension_count += lcaps.count_extensions;
+ while (uv_fs_scandir_next(&req, &dent) != UV_EOF) {
+ if (strlen(dent.name) < 7)
+ continue;
- continue;
+ lwsl_notice(" %s\n", dent.name);
+
+ snprintf(path, sizeof(path) - 1, "%s/%s", *d, dent.name);
+ if (uv_dlopen(path, &lib)) {
+ uv_dlerror(&lib);
+ lwsl_err("Error loading DSO: %s\n", lib.errmsg);
+ goto bail;
+ }
+ /* we could open it, can we get his init function? */
+ m = snprintf(path, sizeof(path) - 1, "init_%s",
+ dent.name + 3 /* snip lib... */);
+ path[m - 3] = '\0'; /* snip the .so */
+ if (uv_dlsym(&lib, path, &v)) {
+ uv_dlerror(&lib);
+ lwsl_err("Failed to get init on %s: %s",
+ dent.name, lib.errmsg);
+ goto bail;
+ }
+ initfunc = (lws_plugin_init_func)v;
+ lcaps.api_magic = LWS_PLUGIN_API_MAGIC;
+ m = initfunc(context, &lcaps);
+ if (m) {
+ lwsl_err("Initializing %s failed %d\n", dent.name, m);
+ goto skip;
+ }
+
+ plugin = lws_malloc(sizeof(*plugin));
+ if (!plugin) {
+ lwsl_err("OOM\n");
+ goto bail;
+ }
+ plugin->list = context->plugin_list;
+ context->plugin_list = plugin;
+ strncpy(plugin->name, dent.name, sizeof(plugin->name) - 1);
+ plugin->name[sizeof(plugin->name) - 1] = '\0';
+ plugin->lib = lib;
+ plugin->caps = lcaps;
+ context->plugin_protocol_count += lcaps.count_protocols;
+ context->plugin_extension_count += lcaps.count_extensions;
+
+ continue;
skip:
- uv_dlclose(&lib);
+ uv_dlclose(&lib);
+ }
+bail:
+ uv_fs_req_cleanup(&req);
+ d++;
}
-bail:
- uv_fs_req_cleanup(&req);
uv_loop_close(&loop);
return ret;
* @vhost_name: VHOST: name of vhost, must match external DNS name used to
* access the site, like "warmcat.com" as it's used to match
* Host: header and / or SNI name for SSL.
- * @plugins_dir: CONTEXT: directory to scan for lws protocol plugins at
- * context creation time
+ * @plugin_dirs: CONTEXT: NULL, or NULL-terminated array of directories to
+ * scan for lws protocol plugins at context creation time
* @pvo: VHOST: pointer to optional linked list of per-vhost
* options made accessible to protocols
* @keepalive_timeout: VHOST: (default = 0 = 60s) seconds to allow remote
unsigned int timeout_secs; /* VH */
const char *ecdh_curve; /* VH */
const char *vhost_name; /* VH */
- const char *plugins_dir; /* context */
+ const char * const *plugin_dirs; /* context */
const struct lws_protocol_vhost_options *pvo; /* VH */
int keepalive_timeout; /* VH */
const char *log_filepath; /* VH */
}
LWS_VISIBLE int
-lws_plat_plugins_init(struct lws_context * context, const char *d)
+lws_plat_plugins_init(struct lws_context * context, const char * const *d)
{
struct lws_plugin_capability lcaps;
struct lws_plugin *plugin;
char path[256];
void *l;
+ lwsl_notice(" Plugins:\n");
- n = scandir(d, &namelist, filter, alphasort);
- if (n < 0) {
- lwsl_err("Scandir on %s failed\n", d);
- return 1;
- }
+ while (d && *d) {
+ n = scandir(*d, &namelist, filter, alphasort);
+ if (n < 0) {
+ lwsl_err("Scandir on %s failed\n", *d);
+ return 1;
+ }
- lwsl_notice(" Plugins:\n");
+ for (i = 0; i < n; i++) {
+ if (strlen(namelist[i]->d_name) < 7)
+ goto inval;
- for (i = 0; i < n; i++) {
- if (strlen(namelist[i]->d_name) < 7)
- goto inval;
+ lwsl_notice(" %s\n", namelist[i]->d_name);
- lwsl_notice(" %s\n", namelist[i]->d_name);
+ snprintf(path, sizeof(path) - 1, "%s/%s", *d,
+ namelist[i]->d_name);
+ l = dlopen(path, RTLD_NOW);
+ if (!l) {
+ lwsl_err("Error loading DSO: %s\n", dlerror());
+ while (i++ < n)
+ free(namelist[i]);
+ goto bail;
+ }
+ /* we could open it, can we get his init function? */
+ m = snprintf(path, sizeof(path) - 1, "init_%s",
+ namelist[i]->d_name + 3 /* snip lib... */);
+ path[m - 3] = '\0'; /* snip the .so */
+ initfunc = dlsym(l, path);
+ if (!initfunc) {
+ lwsl_err("Failed to get init on %s: %s",
+ namelist[i]->d_name, dlerror());
+ dlclose(l);
+ }
+ lcaps.api_magic = LWS_PLUGIN_API_MAGIC;
+ m = initfunc(context, &lcaps);
+ if (m) {
+ lwsl_err("Initializing %s failed %d\n",
+ namelist[i]->d_name, m);
+ dlclose(l);
+ goto skip;
+ }
- snprintf(path, sizeof(path) - 1, "%s/%s", d,
- namelist[i]->d_name);
- l = dlopen(path, RTLD_NOW);
- if (!l) {
- lwsl_err("Error loading DSO: %s\n", dlerror());
- while (i++ < n)
- free(namelist[i]);
- goto bail;
- }
- /* we could open it, can we get his init function? */
- m = snprintf(path, sizeof(path) - 1, "init_%s",
- namelist[i]->d_name + 3 /* snip lib... */);
- path[m - 3] = '\0'; /* snip the .so */
- initfunc = dlsym(l, path);
- if (!initfunc) {
- lwsl_err("Failed to get init on %s: %s",
- namelist[i]->d_name, dlerror());
- dlclose(l);
- }
- lcaps.api_magic = LWS_PLUGIN_API_MAGIC;
- m = initfunc(context, &lcaps);
- if (m) {
- lwsl_err("Initializing %s failed %d\n",
- namelist[i]->d_name, m);
- dlclose(l);
- goto skip;
- }
+ plugin = lws_malloc(sizeof(*plugin));
+ if (!plugin) {
+ lwsl_err("OOM\n");
+ goto bail;
+ }
+ plugin->list = context->plugin_list;
+ context->plugin_list = plugin;
+ strncpy(plugin->name, namelist[i]->d_name, sizeof(plugin->name) - 1);
+ plugin->name[sizeof(plugin->name) - 1] = '\0';
+ plugin->l = l;
+ plugin->caps = lcaps;
+ context->plugin_protocol_count += lcaps.count_protocols;
+ context->plugin_extension_count += lcaps.count_extensions;
+
+ free(namelist[i]);
+ continue;
- plugin = lws_malloc(sizeof(*plugin));
- if (!plugin) {
- lwsl_err("OOM\n");
- goto bail;
+ skip:
+ dlclose(l);
+ inval:
+ free(namelist[i]);
}
- plugin->list = context->plugin_list;
- context->plugin_list = plugin;
- strncpy(plugin->name, namelist[i]->d_name, sizeof(plugin->name) - 1);
- plugin->name[sizeof(plugin->name) - 1] = '\0';
- plugin->l = l;
- plugin->caps = lcaps;
- context->plugin_protocol_count += lcaps.count_protocols;
- context->plugin_extension_count += lcaps.count_extensions;
-
- free(namelist[i]);
- continue;
-
-skip:
- dlclose(l);
-inval:
- free(namelist[i]);
+ free(namelist);
+ d++;
}
bail:
context->fops.write = _lws_plat_file_write;
#ifdef LWS_WITH_PLUGINS
- if (info->plugins_dir)
- lws_plat_plugins_init(context, info->plugins_dir);
+ if (info->plugin_dirs)
+ lws_plat_plugins_init(context, info->plugin_dirs);
#endif
return 0;
lws_libuv_closehandle(struct lws *wsi);
LWS_VISIBLE LWS_EXTERN int
-lws_plat_plugins_init(struct lws_context * context, const char *d);
+lws_plat_plugins_init(struct lws_context * context, const char * const *d);
LWS_VISIBLE LWS_EXTERN int
lws_plat_plugins_destroy(struct lws_context * context);
"global.count-threads",
"global.init-ssl",
"global.server-string",
+ "global.plugin-dir"
};
enum lejp_global_paths {
LEJPGP_COUNT_THREADS,
LWJPGP_INIT_SSL,
LEJPGP_SERVER_STRING,
+ LEJPGP_PLUGIN_DIR
};
static const char * const paths_vhosts[] = {
LEJPVP_KEEPALIVE_TIMEOUT,
};
+#define MAX_PLUGIN_DIRS 10
+
struct jpargs {
struct lws_context_creation_info *info;
struct lws_context *context;
struct lws_protocol_vhost_options *pvo;
struct lws_http_mount m;
+ const char **plugin_dirs;
+ int count_plugin_dirs;
};
static void *
case LEJPGP_SERVER_STRING:
a->info->server_string = a->p;
break;
+ case LEJPGP_PLUGIN_DIR:
+ if (a->count_plugin_dirs == MAX_PLUGIN_DIRS - 1) {
+ lwsl_err("Too many plugin dirs\n");
+ return -1;
+ }
+ a->plugin_dirs[a->count_plugin_dirs++] = a->p;
+ break;
default:
return 0;
char **cs, int *len)
{
struct jpargs a;
+ const char * const *old = info->plugin_dirs;
+
+ memset(&a, 0, sizeof(a));
a.info = info;
a.p = *cs;
a.end = (a.p + *len) - 1;
a.valid = 0;
+ lwsws_align(&a);
+ info->plugin_dirs = (void *)a.p;
+ a.plugin_dirs = (void *)a.p; /* writeable version */
+ a.p += MAX_PLUGIN_DIRS * sizeof(void *);
+
+ /* copy any default paths */
+
+ while (old && *old) {
+ a.plugin_dirs[a.count_plugin_dirs++] = *old;
+ old++;
+ }
+
if (lwsws_get_config(&a, "/etc/lwsws/conf", paths_global,
ARRAY_SIZE(paths_global), lejp_globals_cb) > 1)
return 1;
ARRAY_SIZE(paths_global), lejp_globals_cb) > 1)
return 1;
+ a.plugin_dirs[a.count_plugin_dirs] = NULL;
+
*cs = a.p;
*len = a.end - a.p;
{
struct jpargs a;
+ memset(&a, 0, sizeof(a));
+
a.info = info;
a.p = *cs;
a.end = a.p + *len;
{ NULL, NULL, NULL /* terminator */ }
};
+static const char * const plugin_dirs[] = {
+ INSTALL_DATADIR"/libwebsockets-test-server/plugins/",
+ NULL
+};
+
static struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "debug", required_argument, NULL, 'd' },
}
#endif
+
+
int main(int argc, char **argv)
{
struct lws_context_creation_info info;
LWS_SERVER_OPTION_EXPLICIT_VHOSTS |
LWS_SERVER_OPTION_LIBUV;
- info.plugins_dir = INSTALL_DATADIR"/libwebsockets-test-server/plugins/";
-
+ info.plugin_dirs = plugin_dirs;
lwsl_notice("Using config dir: \"%s\"\n", config_dir);
/*
{ NULL, 0, 0, 0 }
};
+static const char * const plugin_dirs[] = {
+ INSTALL_DATADIR"/libwebsockets-test-server/plugins/",
+ NULL
+};
+
int main(int argc, char **argv)
{
struct lws_context_creation_info info;
"!AES256-SHA256";
/* tell lws to look for protocol plugins here */
- info.plugins_dir = INSTALL_DATADIR"/libwebsockets-test-server/plugins/";
+ info.plugin_dirs = plugin_dirs;
/* tell lws about our mount we want */
info.mounts = &mount;