libwebsockets
Lightweight C library for HTML5 websockets
lws-protocols-plugins.h
Go to the documentation of this file.
1/*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24
25/*! \defgroup Protocols-and-Plugins Protocols and Plugins
26 * \ingroup lwsapi
27 *
28 * ##Protocol and protocol plugin -related apis
29 *
30 * Protocols bind ws protocol names to a custom callback specific to that
31 * protocol implementaion.
32 *
33 * A list of protocols can be passed in at context creation time, but it is
34 * also legal to leave that NULL and add the protocols and their callback code
35 * using plugins.
36 *
37 * Plugins are much preferable compared to cut and pasting code into an
38 * application each time, since they can be used standalone.
39 */
40///@{
41/** struct lws_protocols - List of protocols and handlers client or server
42 * supports. */
43
45 const char *name;
46 /**< Protocol name that must match the one given in the client
47 * Javascript new WebSocket(url, 'protocol') name. */
49 /**< The service callback used for this protocol. It allows the
50 * service action for an entire protocol to be encapsulated in
51 * the protocol-specific callback */
53 /**< Each new connection using this protocol gets
54 * this much memory allocated on connection establishment and
55 * freed on connection takedown. A pointer to this per-connection
56 * allocation is passed into the callback in the 'user' parameter */
58 /**< lws allocates this much space for rx data and informs callback
59 * when something came. Due to rx flow control, the callback may not
60 * be able to consume it all without having to return to the event
61 * loop. That is supported in lws.
62 *
63 * If .tx_packet_size is 0, this also controls how much may be sent at
64 * once for backwards compatibility.
65 */
66 unsigned int id;
67 /**< ignored by lws, but useful to contain user information bound
68 * to the selected protocol. For example if this protocol was
69 * called "myprotocol-v2", you might set id to 2, and the user
70 * code that acts differently according to the version can do so by
71 * switch (wsi->a.protocol->id), user code might use some bits as
72 * capability flags based on selected protocol version, etc. */
73 void *user; /**< ignored by lws, but user code can pass a pointer
74 here it can later access from the protocol callback */
76 /**< 0 indicates restrict send() size to .rx_buffer_size for backwards-
77 * compatibility.
78 * If greater than zero, a single send() is restricted to this amount
79 * and any remainder is buffered by lws and sent afterwards also in
80 * these size chunks. Since that is expensive, it's preferable
81 * to restrict one fragment you are trying to send to match this
82 * size.
83 */
84
85 /* Add new things just above here ---^
86 * This is part of the ABI, don't needlessly break compatibility */
87};
88
89#define LWS_PROTOCOL_LIST_TERM { NULL, NULL, 0, 0, 0, NULL, 0 }
90
91/**
92 * lws_vhost_name_to_protocol() - get vhost's protocol object from its name
93 *
94 * \param vh: vhost to search
95 * \param name: protocol name
96 *
97 * Returns NULL or a pointer to the vhost's protocol of the requested name
98 */
99LWS_VISIBLE LWS_EXTERN const struct lws_protocols *
100lws_vhost_name_to_protocol(struct lws_vhost *vh, const char *name);
101
102/**
103 * lws_get_protocol() - Returns a protocol pointer from a websocket
104 * connection.
105 * \param wsi: pointer to struct websocket you want to know the protocol of
106 *
107 *
108 * Some apis can act on all live connections of a given protocol,
109 * this is how you can get a pointer to the active protocol if needed.
110 */
111LWS_VISIBLE LWS_EXTERN const struct lws_protocols *
112lws_get_protocol(struct lws *wsi);
113
114/** lws_protocol_get() - deprecated: use lws_get_protocol */
115LWS_VISIBLE LWS_EXTERN const struct lws_protocols *
116lws_protocol_get(struct lws *wsi) LWS_WARN_DEPRECATED;
117
118/**
119 * lws_protocol_vh_priv_zalloc() - Allocate and zero down a protocol's per-vhost
120 * storage
121 * \param vhost: vhost the instance is related to
122 * \param prot: protocol the instance is related to
123 * \param size: bytes to allocate
124 *
125 * Protocols often find it useful to allocate a per-vhost struct, this is a
126 * helper to be called in the per-vhost init LWS_CALLBACK_PROTOCOL_INIT
127 */
128LWS_VISIBLE LWS_EXTERN void *
129lws_protocol_vh_priv_zalloc(struct lws_vhost *vhost,
130 const struct lws_protocols *prot, int size);
131
132/**
133 * lws_protocol_vh_priv_get() - retreive a protocol's per-vhost storage
134 *
135 * \param vhost: vhost the instance is related to
136 * \param prot: protocol the instance is related to
137 *
138 * Recover a pointer to the allocated per-vhost storage for the protocol created
139 * by lws_protocol_vh_priv_zalloc() earlier
140 */
141LWS_VISIBLE LWS_EXTERN void *
142lws_protocol_vh_priv_get(struct lws_vhost *vhost,
143 const struct lws_protocols *prot);
144
145/**
146 * lws_vhd_find_by_pvo() - find a partner vhd
147 *
148 * \param cx: the lws_context
149 * \param protname: the name of the lws_protocol the vhd belongs to
150 * \param pvo_name: the name of a pvo that must exist bound to the vhd
151 * \param pvo_value: the required value of the named pvo
152 *
153 * This allows architectures with multiple protocols bound together to
154 * cleanly discover partner protocol instances even on completely
155 * different vhosts. For example, a proxy may consist of two protocols
156 * listening on different vhosts, and there may be multiple instances
157 * of the proxy in the same process. It's desirable that each side of
158 * the proxy is an independent protocol that can be freely bound to any
159 * vhost, eg, allowing Unix Domain to tls / h2 proxying, or each side
160 * bound to different network interfaces for localhost-only visibility
161 * on one side, using existing vhost management.
162 *
163 * That leaves the problem that the two sides have to find each other
164 * and bind at runtime. This api allows each side to specify the
165 * protocol name, and a common pvo name and pvo value that indicates
166 * the two sides belong together, and search through all the instantiated
167 * vhost-protocols looking for a match. If found, the private allocation
168 * (aka "vhd" of the match is returned). NULL is returned on no match.
169 *
170 * Since this can only succeed when called by the last of the two
171 * protocols to be instantiated, both sides should call it and handle
172 * NULL gracefully, since it may mean that they were first and their
173 * partner vhsot-protocol has not been instantiated yet.
174 */
175LWS_VISIBLE LWS_EXTERN void *
176lws_vhd_find_by_pvo(struct lws_context *cx, const char *protname,
177 const char *pvo_name, const char *pvo_value);
178
179
180/**
181 * lws_adjust_protocol_psds - change a vhost protocol's per session data size
182 *
183 * \param wsi: a connection with the protocol to change
184 * \param new_size: the new size of the per session data size for the protocol
185 *
186 * Returns user_space for the wsi, after allocating
187 *
188 * This should not be used except to initalize a vhost protocol's per session
189 * data size one time, before any connections are accepted.
190 *
191 * Sometimes the protocol wraps another protocol and needs to discover and set
192 * its per session data size at runtime.
193 */
194LWS_VISIBLE LWS_EXTERN void *
195lws_adjust_protocol_psds(struct lws *wsi, size_t new_size);
196
197/**
198 * lws_finalize_startup() - drop initial process privileges
199 *
200 * \param context: lws context
201 *
202 * This is called after the end of the vhost protocol initializations, but
203 * you may choose to call it earlier
204 */
205LWS_VISIBLE LWS_EXTERN int
206lws_finalize_startup(struct lws_context *context);
207
208/**
209 * lws_pvo_search() - helper to find a named pvo in a linked-list
210 *
211 * \param pvo: the first pvo in the linked-list
212 * \param name: the name of the pvo to return if found
213 *
214 * Returns NULL, or a pointer to the name pvo in the linked-list
215 */
216LWS_VISIBLE LWS_EXTERN const struct lws_protocol_vhost_options *
217lws_pvo_search(const struct lws_protocol_vhost_options *pvo, const char *name);
218
219/**
220 * lws_pvo_get_str() - retreive a string pvo value
221 *
222 * \param in: the first pvo in the linked-list
223 * \param name: the name of the pvo to return if found
224 * \param result: pointer to a const char * to get the result if any
225 *
226 * Returns 0 if found and *result set, or nonzero if not found
227 */
228LWS_VISIBLE LWS_EXTERN int
229lws_pvo_get_str(void *in, const char *name, const char **result);
230
231LWS_VISIBLE LWS_EXTERN int
232lws_protocol_init(struct lws_context *context);
233
234#define LWS_PLUGIN_API_MAGIC 191
235
236/*
237 * Abstract plugin header for any kind of plugin class, always at top of
238 * actual class plugin export type.
239 *
240 * The export type object must be exported with the same name as the plugin
241 * file, eg, libmyplugin.so must export a const one of these as the symbol
242 * "myplugin".
243 *
244 * That is the only expected export from the plugin.
245 */
246
247typedef struct lws_plugin_header {
248 const char *name;
249 const char *_class;
250 const char *lws_build_hash; /* set to LWS_BUILD_HASH */
251
252 unsigned int api_magic;
253 /* set to LWS_PLUGIN_API_MAGIC at plugin build time */
254
255 /* plugin-class specific superclass data follows */
256} lws_plugin_header_t;
257
258/*
259 * "lws_protocol_plugin" class export, for lws_protocol implementations done
260 * as plugins
261 */
262typedef struct lws_plugin_protocol {
263 lws_plugin_header_t hdr;
264
265 const struct lws_protocols *protocols; /**< array of supported protocols provided by plugin */
266 const struct lws_extension *extensions; /**< array of extensions provided by plugin */
267 int count_protocols; /**< how many protocols */
268 int count_extensions; /**< how many extensions */
269} lws_plugin_protocol_t;
270
271
272/*
273 * This is the dynamic, runtime created part of the plugin instantiation.
274 * These are kept in a linked-list and destroyed with the context.
275 */
276
278 struct lws_plugin *list; /**< linked list */
279
280 const lws_plugin_header_t *hdr;
281
282 union {
283#if defined(LWS_WITH_LIBUV) && defined(UV_ERRNO_MAP)
284#if (UV_VERSION_MAJOR > 0)
285 uv_lib_t lib; /**< shared library pointer */
286#endif
287#endif
288 void *l; /**< */
289 } u;
290};
291
292/*
293 * Event lib library plugin type (when LWS_WITH_EVLIB_PLUGINS)
294 * Public so new event libs can equally be supported outside lws itself
295 */
296
297typedef struct lws_plugin_evlib {
298 lws_plugin_header_t hdr;
299 const struct lws_event_loop_ops *ops;
300} lws_plugin_evlib_t;
301
302typedef int (*each_plugin_cb_t)(struct lws_plugin *p, void *user);
303
304/**
305 * lws_plugins_init() - dynamically load plugins of matching class from dirs
306 *
307 * \param pplugin: pointer to linked-list for this kind of plugin
308 * \param d: array of directory paths to look in
309 * \param _class: class string that plugin must declare
310 * \param filter: NULL, or a string that must appear after the third char of the plugin filename
311 * \param each: NULL, or each_plugin_cb_t callback for each instantiated plugin
312 * \param each_user: pointer passed to each callback
313 *
314 * Allows you to instantiate a class of plugins to a specified linked-list.
315 * The each callback allows you to init each inistantiated callback and pass a
316 * pointer each_user to it.
317 *
318 * To take down the plugins, pass a pointer to the linked-list head to
319 * lws_plugins_destroy.
320 *
321 * This is used for lws protocol plugins but you can define your own plugin
322 * class name like "mypluginclass", declare it in your plugin headers, and load
323 * your own plugins to your own list using this api the same way.
324 */
325LWS_VISIBLE LWS_EXTERN int
326lws_plugins_init(struct lws_plugin **pplugin, const char * const *d,
327 const char *_class, const char *filter,
328 each_plugin_cb_t each, void *each_user);
329
330/**
331 * lws_plugins_destroy() - dynamically unload list of plugins
332 *
333 * \param pplugin: pointer to linked-list for this kind of plugin
334 * \param each: NULL, or each_plugin_cb_t callback for each instantiated plugin
335 * \param each_user: pointer passed to each callback
336 *
337 * Allows you to destroy a class of plugins from a specified linked-list
338 * created by a call to lws_plugins_init().
339 *
340 * The each callback allows you to deinit each inistantiated callback and pass a
341 * pointer each_user to it, just before its footprint is destroyed.
342 */
343LWS_VISIBLE LWS_EXTERN int
345 void *each_user);
346
347#if defined(LWS_WITH_PLUGINS_BUILTIN)
348
349/* provide exports for builtin plugin protocols */
350
351extern const struct lws_protocols post_demo_protocols[1];
352extern const struct lws_protocols lws_raw_proxy_protocols[1];
353extern const struct lws_protocols lws_status_protocols[1];
354extern const struct lws_protocols lws_mirror_protocols[1];
355extern const struct lws_protocols lws_ssh_base_protocols[2];
356extern const struct lws_protocols post_demo_protocols[1];
357extern const struct lws_protocols dumb_increment_protocols[1];
358extern const struct lws_protocols deaddrop_protocols[1];
359extern const struct lws_protocols lws_raw_test_protocols[1];
360extern const struct lws_protocols lws_sshd_demo_protocols[1];
361extern const struct lws_protocols lws_acme_client_protocols[1];
362extern const struct lws_protocols client_loopback_test_protocols[1];
363extern const struct lws_protocols fulltext_demo_protocols[1];
364extern const struct lws_protocols lws_openmetrics_export_protocols[
365#if defined(LWS_WITH_SERVER) && defined(LWS_WITH_CLIENT) && defined(LWS_ROLE_WS)
366 4
367#else
368#if defined(LWS_WITH_SERVER)
369 3
370#else
371 1
372#endif
373#endif
374 ];
375
376#define LWSOMPROIDX_DIRECT_HTTP_SERVER 0
377#define LWSOMPROIDX_PROX_HTTP_SERVER 1
378#define LWSOMPROIDX_PROX_WS_SERVER 2
379#define LWSOMPROIDX_PROX_WS_CLIENT 3
380
381#endif
382
383///@}
const lws_plugin_header_t * hdr
lws_plugin_header_t hdr
struct lws_plugin * list
const struct lws_event_loop_ops * ops
lws_plugin_header_t hdr
lws_callback_function * callback
const struct lws_protocols * protocols
const struct lws_extension * extensions
LWS_VISIBLE LWS_EXTERN int lws_finalize_startup(struct lws_context *context)
LWS_VISIBLE LWS_EXTERN int lws_pvo_get_str(void *in, const char *name, const char **result)
LWS_VISIBLE LWS_EXTERN const struct lws_protocols * lws_vhost_name_to_protocol(struct lws_vhost *vh, const char *name)
LWS_VISIBLE LWS_EXTERN void * lws_adjust_protocol_psds(struct lws *wsi, size_t new_size)
LWS_VISIBLE LWS_EXTERN int lws_protocol_init(struct lws_context *context)
LWS_VISIBLE LWS_EXTERN const struct lws_protocols * lws_get_protocol(struct lws *wsi)
LWS_VISIBLE LWS_EXTERN void * lws_protocol_vh_priv_get(struct lws_vhost *vhost, const struct lws_protocols *prot)
int(* each_plugin_cb_t)(struct lws_plugin *p, void *user)
LWS_VISIBLE LWS_EXTERN void * lws_vhd_find_by_pvo(struct lws_context *cx, const char *protname, const char *pvo_name, const char *pvo_value)
LWS_VISIBLE LWS_EXTERN const struct lws_protocol_vhost_options * lws_pvo_search(const struct lws_protocol_vhost_options *pvo, const char *name)
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 void * lws_protocol_vh_priv_zalloc(struct lws_vhost *vhost, const struct lws_protocols *prot, int size)
LWS_VISIBLE LWS_EXTERN int lws_plugins_destroy(struct lws_plugin **pplugin, each_plugin_cb_t each, void *each_user)