1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

lws_plugins

This commit is contained in:
Andy Green 2020-08-30 07:39:27 +01:00
parent f53db84117
commit 1d05f429dc
8 changed files with 135 additions and 18 deletions

View file

@ -390,3 +390,8 @@ endif()
if (NOT LWS_WITH_SSL)
set(LWS_WITHOUT_BUILTIN_SHA1 OFF)
endif()
if (LWS_WITH_PLUGINS OR (LWS_WITH_EVLIB_PLUGINS AND LWS_WITH_EVENT_LIBS))
set(LWS_WITH_PLUGINS_API 1)
endif()

View file

@ -92,7 +92,7 @@ option(LWS_WITH_LWSWS "Libwebsockets Webserver" OFF)
option(LWS_WITH_CGI "Include CGI (spawn process with network-connected stdin/out/err) APIs" OFF)
option(LWS_IPV6 "Compile with support for ipv6" OFF)
option(LWS_UNIX_SOCK "Compile with support for UNIX domain socket if OS supports it" ON)
option(LWS_WITH_PLUGINS "Support plugins for protocols and extensions" OFF)
option(LWS_WITH_PLUGINS "Support plugins for protocols and extensions (implies LWS_WITH_PLUGINS_API)" OFF)
option(LWS_WITH_HTTP_PROXY "Support for active HTTP proxying" OFF)
option(LWS_WITH_ZIP_FOPS "Support serving pre-zipped files" OFF)
option(LWS_WITH_SOCKS5 "Allow use of SOCKS5 proxy on client connections" OFF)
@ -250,6 +250,7 @@ option(LWS_WITH_FSMOUNT "Overlayfs and fallback mounting apis" OFF)
option(LWS_WITH_FANALYZER "Enable gcc -fanalyzer if compiler supports" OFF)
option(LWS_HTTP_HEADERS_ALL "Override header reduction optimization and include all like older lws versions" OFF)
option(LWS_WITH_SUL_DEBUGGING "Enable zombie lws_sul checking on object deletion" OFF)
option(LWS_WITH_PLUGINS_API "Build generic lws_plugins apis (see LWS_WITH_PLUGINS to also build protocol plugins)" OFF)
#
# to use miniz, enable both LWS_WITH_ZLIB and LWS_WITH_MINIZ

View file

@ -0,0 +1,105 @@
# lws_plugins
Lws now offers apis to manage your own user plugins with `LWS_WITH_PLUGINS_API`.
Lws uses these apis internally for protocol plugins and event loop plugins
if they're selected for build. But they are also exported for user code to
use them how you like.
## Creating your plugin export
### Specifying your plugin export type
Lws plugins have a single exported struct with a specified header and a user
defined remainder. The public `lws_plugin_header_t` describes the common
plugin export header, it's defined via libwebsockets.h as
```
typedef struct lws_plugin_header {
const char *name;
const char *_class;
unsigned int api_magic;
/* set to LWS_PLUGIN_API_MAGIC at plugin build time */
/* plugin-class specific superclass data follows */
} lws_plugin_header_t;
```
The exported symbol name itself must match the plugin filename, for
example if the symbol name is `my_plugin`, then the filename of the
plugin might be `libmyapp-my_plugin.so` or similar... the matching
part is after the first `-` or `_`, up to the first `.`. The exact
details differ by platform but these rules cover the supported
platforms. If lws has the filename of the plugin, it can then
deduce the symbol export it should look for in the plugin.
`name` is a freeform human-readable description for the plugin.
`_class` is shared by your plugins and used to select them from other kinds
of plugin that may be in the same dir. So choose a unique name like
`"myapp xxx plugin"` or whatever shared by all plugins of that class.
`api_magic` is set to `LWS_PLUGIN_API_MAGIC` to detect if the plugin is
incompatible with the lws plugin apis version.
So for example your plugin type wrapping the header might look like
```
typedef struct myapp_plugin {
lws_plugin_header_t hdr; /* must be first */
/* optional extra data like function pointers from your plugin */
mytype_t mymember;
/* ... */
} myapp_plugin_t;
```
Typically, you will put function pointers to whatever capability your plugin
class offers as the additional members.
## Building your own plugins
Plugins are built standalone, cmake is recommended but you can do what you want.
The only requirement is the single visible export of the plugin name, eg
```
const myapp_plugin_t my_plugin = {
.hdr = {
"my_plugin",
"myapp xxx plugin",
LWS_PLUGIN_API_MAGIC
},
.mymember = my_plugin_init,
/*...*/
};
```
## Bringing in plugins at runtime
Lws provides an api to import plugins into the process space and another to
remove and destroy plugins.
You can take two approaches depending on what you're doing, either bring in and
later destroy a whole class of plugins at once, and walk them via a linked-list,
or bring in and later destroy a single specific plugin from the class by filtering
on its specific export name.
See `include/libwebsockets/lws-protocols-plugins.h` for documentation.
```
LWS_VISIBLE LWS_EXTERN int
lws_plugins_init(struct lws_plugin **pplugin, const char * const *d,
const char *_class, const char *filter,
each_plugin_cb_t each, void *each_user);
LWS_VISIBLE LWS_EXTERN int
lws_plugins_destroy(struct lws_plugin **pplugin, each_plugin_cb_t each,
void *each_user);
```
`struct lws_plugin` is a public struct that contains the linked-list of loaded
plugins and a pointer to its exported header object, so you can walk this
after loading.

View file

@ -193,4 +193,5 @@
#cmakedefine LWS_WITH_EVENT_LIBS
#cmakedefine LWS_WITH_EVLIB_PLUGINS
#cmakedefine LWS_WITH_LIBUV_INTERNAL
#cmakedefine LWS_WITH_PLUGINS_API

View file

@ -304,15 +304,14 @@ lws_dir_rm_rf_cb(const char *dirpath, void *user, struct lws_dir_entry *lde)
#endif
#if defined(LWS_WITH_PLUGINS) || \
(defined(LWS_WITH_EVLIB_PLUGINS) && defined(LWS_WITH_EVENT_LIBS))
#if defined(LWS_WITH_PLUGINS_API)
struct lws_plugins_args {
struct lws_plugin **pplugin;
const char *_class;
const char *filter;
each_plugin_cb_t each;
void *each_user;
struct lws_plugin **pplugin;
const char *_class;
const char *filter;
each_plugin_cb_t each;
void *each_user;
};
static int

View file

@ -65,7 +65,7 @@ if (LWS_WITH_NETWORK)
endif()
endif()
if (LWS_WITH_PLUGINS OR LWS_WITH_EVLIB_PLUGINS)
if (LWS_WITH_PLUGINS_API)
list(APPEND SOURCES plat/unix/unix-plugins.c)
endif()

View file

@ -29,10 +29,7 @@
#include <pwd.h>
#include <grp.h>
#if defined(LWS_WITH_PLUGINS) || defined(LWS_WITH_EVLIB_PLUGINS)
#include <dlfcn.h>
#endif
const lws_plugin_header_t *
lws_plat_dlopen(struct lws_plugin **pplugin, const char *libpath,

View file

@ -27,8 +27,11 @@
#endif
#include "private-lib-core.h"
#if (defined(LWS_WITH_PLUGINS) || defined(LWS_WITH_EVLIB_PLUGINS)) && \
(UV_VERSION_MAJOR > 0)
/*
* ie, if the plugins api needed at all
*/
#if defined(LWS_WITH_PLUGINS_API) && (UV_VERSION_MAJOR > 0)
const lws_plugin_header_t *
lws_plat_dlopen(struct lws_plugin **pplugin, const char *libpath,
@ -105,6 +108,14 @@ lws_plat_destroy_dl(struct lws_plugin *p)
return uv_dlclose(&p->u.lib);
}
#endif
/*
* Specifically for protocol plugins support
*/
#if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0)
static int
protocol_plugin_cb(struct lws_plugin *pin, void *each_user)
{
@ -122,8 +133,7 @@ protocol_plugin_cb(struct lws_plugin *pin, void *each_user)
int
lws_plat_plugins_init(struct lws_context *context, const char * const *d)
{
#if (defined(LWS_WITH_PLUGINS) || defined(LWS_WITH_EVLIB_PLUGINS)) && \
(UV_VERSION_MAJOR > 0)
#if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0)
if (info->plugin_dirs) {
uv_loop_init(&context->uv.loop);
lws_plugins_init(&context->plugin_list, info->plugin_dirs,
@ -138,8 +148,7 @@ lws_plat_plugins_init(struct lws_context *context, const char * const *d)
int
lws_plat_plugins_destroy(struct lws_context * context)
{
#if (defined(LWS_WITH_PLUGINS) || defined(LWS_WITH_EVLIB_PLUGINS)) && \
(UV_VERSION_MAJOR > 0)
#if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0)
if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV) &&
context->plugin_list) {
lws_plugins_destroy(&context->plugin_list, NULL, NULL);