lws-protocols-plugins.h (14480B)
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 44struct lws_protocols { 45 const char *name; 46 /**< Protocol name that must match the one given in the client 47 * Javascript new WebSocket(url, 'protocol') name. */ 48 lws_callback_function *callback; 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 */ 52 size_t per_session_data_size; 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 */ 57 size_t rx_buffer_size; 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 */ 75 size_t tx_packet_size; 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 277struct lws_plugin { 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 344lws_plugins_destroy(struct lws_plugin **pplugin, each_plugin_cb_t each, 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///@}