xref: /aosp_15_r20/external/libwebsockets/READMEs/README.lws_plugins.md (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1# lws_plugins
2
3Lws now offers apis to manage your own user plugins with `LWS_WITH_PLUGINS_API`.
4Lws uses these apis internally for protocol plugins and event loop plugins
5if they're selected for build.  But they are also exported for user code to
6use them how you like.
7
8## Creating your plugin export
9
10### Specifying your plugin export type
11
12Lws plugins have a single exported struct with a specified header and a user
13defined remainder.  The public `lws_plugin_header_t` describes the common
14plugin export header, it's defined via libwebsockets.h as
15
16```
17typedef struct lws_plugin_header {
18	const char *name;
19	const char *_class;
20
21	unsigned int api_magic;
22	/* set to LWS_PLUGIN_API_MAGIC at plugin build time */
23
24	/* plugin-class specific superclass data follows */
25} lws_plugin_header_t;
26```
27
28The exported symbol name itself must match the plugin filename, for
29example if the symbol name is `my_plugin`, then the filename of the
30plugin might be `libmyapp-my_plugin.so` or similar... the matching
31part is after the first `-` or `_`, up to the first `.`.  The exact
32details differ by platform but these rules cover the supported
33platforms.  If lws has the filename of the plugin, it can then
34deduce the symbol export it should look for in the plugin.
35
36`name` is a freeform human-readable description for the plugin.
37
38`_class` is shared by your plugins and used to select them from other kinds
39of plugin that may be in the same dir.  So choose a unique name like
40`"myapp xxx plugin"` or whatever shared by all plugins of that class.
41
42`api_magic` is set to `LWS_PLUGIN_API_MAGIC` to detect if the plugin is
43incompatible with the lws plugin apis version.
44
45So for example your plugin type wrapping the header might look like
46
47```
48typedef struct myapp_plugin {
49        lws_plugin_header_t	hdr; /* must be first */
50
51	/* optional extra data like function pointers from your plugin */
52	mytype_t		mymember;
53	/* ... */
54} myapp_plugin_t;
55```
56
57Typically, you will put function pointers to whatever capability your plugin
58class offers as the additional members.
59
60## Building your own plugins
61
62Plugins are built standalone, cmake is recommended but you can do what you want.
63
64The only requirement is the single visible export of the plugin name, eg
65
66```
67const myapp_plugin_t my_plugin = {
68	.hdr = {
69		"my_plugin",
70		"myapp xxx plugin",
71		LWS_PLUGIN_API_MAGIC
72	},
73
74	.mymember	= my_plugin_init,
75	/*...*/
76};
77```
78
79## Bringing in plugins at runtime
80
81Lws provides an api to import plugins into the process space and another to
82remove and destroy plugins.
83
84You can take two approaches depending on what you're doing, either bring in and
85later destroy a whole class of plugins at once, and walk them via a linked-list,
86or bring in and later destroy a single specific plugin from the class by filtering
87on its specific export name.
88
89See `include/libwebsockets/lws-protocols-plugins.h` for documentation.
90
91```
92LWS_VISIBLE LWS_EXTERN int
93lws_plugins_init(struct lws_plugin **pplugin, const char * const *d,
94		 const char *_class, const char *filter,
95		 each_plugin_cb_t each, void *each_user);
96
97LWS_VISIBLE LWS_EXTERN int
98lws_plugins_destroy(struct lws_plugin **pplugin, each_plugin_cb_t each,
99		    void *each_user);
100```
101
102`struct lws_plugin` is a public struct that contains the linked-list of loaded
103plugins and a pointer to its exported header object, so you can walk this
104after loading.
105
106