| 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 | |
| 44 | struct 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 | */ |
| 99 | LWS_VISIBLE LWS_EXTERN const struct lws_protocols * |
| 100 | lws_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 | */ |
| 111 | LWS_VISIBLE LWS_EXTERN const struct lws_protocols * |
| 112 | lws_get_protocol(struct lws *wsi); |
| 113 | |
| 114 | /** lws_protocol_get() - deprecated: use lws_get_protocol */ |
| 115 | LWS_VISIBLE LWS_EXTERN const struct lws_protocols * |
| 116 | lws_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 | */ |
| 128 | LWS_VISIBLE LWS_EXTERN void * |
| 129 | lws_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 | */ |
| 141 | LWS_VISIBLE LWS_EXTERN void * |
| 142 | lws_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 | */ |
| 175 | LWS_VISIBLE LWS_EXTERN void * |
| 176 | lws_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 | */ |
| 194 | LWS_VISIBLE LWS_EXTERN void * |
| 195 | lws_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 | */ |
| 205 | LWS_VISIBLE LWS_EXTERN int |
| 206 | lws_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 | */ |
| 216 | LWS_VISIBLE LWS_EXTERN const struct lws_protocol_vhost_options * |
| 217 | lws_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 | */ |
| 228 | LWS_VISIBLE LWS_EXTERN int |
| 229 | lws_pvo_get_str(void *in, const char *name, const char **result); |
| 230 | |
| 231 | LWS_VISIBLE LWS_EXTERN int |
| 232 | lws_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 | |
| 247 | typedef struct { |
| 248 | const char *; |
| 249 | const char *; |
| 250 | const char *; /* set to LWS_BUILD_HASH */ |
| 251 | |
| 252 | unsigned int ; |
| 253 | /* set to LWS_PLUGIN_API_MAGIC at plugin build time */ |
| 254 | |
| 255 | /* plugin-class specific superclass data follows */ |
| 256 | } ; |
| 257 | |
| 258 | /* |
| 259 | * "lws_protocol_plugin" class export, for lws_protocol implementations done |
| 260 | * as plugins |
| 261 | */ |
| 262 | typedef 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 | |
| 277 | struct 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 | |
| 297 | typedef struct lws_plugin_evlib { |
| 298 | lws_plugin_header_t hdr; |
| 299 | const struct lws_event_loop_ops *ops; |
| 300 | } lws_plugin_evlib_t; |
| 301 | |
| 302 | typedef 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 | */ |
| 325 | LWS_VISIBLE LWS_EXTERN int |
| 326 | lws_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 | */ |
| 343 | LWS_VISIBLE LWS_EXTERN int |
| 344 | lws_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 | |
| 351 | extern const struct lws_protocols post_demo_protocols[1]; |
| 352 | extern const struct lws_protocols lws_raw_proxy_protocols[1]; |
| 353 | extern const struct lws_protocols lws_status_protocols[1]; |
| 354 | extern const struct lws_protocols lws_mirror_protocols[1]; |
| 355 | extern const struct lws_protocols lws_ssh_base_protocols[2]; |
| 356 | extern const struct lws_protocols post_demo_protocols[1]; |
| 357 | extern const struct lws_protocols dumb_increment_protocols[1]; |
| 358 | extern const struct lws_protocols deaddrop_protocols[1]; |
| 359 | extern const struct lws_protocols lws_raw_test_protocols[1]; |
| 360 | extern const struct lws_protocols lws_sshd_demo_protocols[1]; |
| 361 | extern const struct lws_protocols lws_acme_client_protocols[1]; |
| 362 | extern const struct lws_protocols client_loopback_test_protocols[1]; |
| 363 | extern const struct lws_protocols fulltext_demo_protocols[1]; |
| 364 | extern 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 | ///@} |
| 384 | |