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#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS 26#define _WINSOCK_DEPRECATED_NO_WARNINGS 27#endif 28#include "private-lib-core.h" 29 30/* 31 * ie, if the plugins api needed at all 32 */ 33 34#if defined(LWS_WITH_PLUGINS_API) && (UV_VERSION_MAJOR > 0) 35 36const lws_plugin_header_t * 37lws_plat_dlopen(struct lws_plugin **pplugin, const char *libpath, 38 const char *sofilename, const char *_class, 39 each_plugin_cb_t each, void *each_user) 40{ 41 const lws_plugin_header_t *hdr; 42 struct lws_plugin *pin; 43 char sym[96], *dot; 44 uv_lib_t lib; 45 void *v; 46 int m; 47 48 lib.errmsg = NULL; 49 lib.handle = NULL; 50 51 if (uv_dlopen(libpath, &lib)) { 52 uv_dlerror(&lib); 53 lwsl_err("Error loading DSO: %s\n", lib.errmsg); 54 uv_dlclose(&lib); 55 return NULL; 56 } 57 58 /* we could open it... can we get his export struct? */ 59 m = lws_snprintf(sym, sizeof(sym) - 1, "%s", sofilename); 60 if (m < 4) 61 goto bail; 62 dot = strchr(sym, '.'); 63 if (dot) 64 *dot = '\0'; /* snip the .so or .lib or what-have-you*/ 65 66 if (uv_dlsym(&lib, sym, &v)) { 67 uv_dlerror(&lib); 68 lwsl_err("%s: Failed to get '%s' on %s: %s\n", 69 __func__, path, libpath, lib.errmsg); 70 goto bail; 71 } 72 73 hdr = (const lws_plugin_header_t *)v; 74 if (hdr->api_magic != LWS_PLUGIN_API_MAGIC) { 75 lwsl_info("%s: plugin %s has outdated api %d (vs %d)\n", 76 __func__, libpath, hdr->api_magic, 77 LWS_PLUGIN_API_MAGIC); 78 goto bail; 79 } 80 81 if (strcmp(hdr->lws_build_hash, LWS_BUILD_HASH)) 82 goto bail; 83 84 if (strcmp(hdr->_class, _class)) 85 goto bail; 86 87 /* 88 * We don't already have one of these, right? 89 */ 90 91 pin = *pplugin; 92 while (pin) { 93 if (!strcmp(pin->hdr->name, hdr->name)) 94 goto bail; 95 pin = pin->list; 96 } 97 98 /* 99 * OK let's bring it in 100 */ 101 102 pin = lws_malloc(sizeof(*pin), __func__); 103 if (!pin) 104 goto bail; 105 106 pin->list = *pplugin; 107 *pplugin = pin; 108 109 pin->u.lib = lib; 110 pin->hdr = hdr; 111 112 if (each) 113 each(pin, each_user); 114 115 return hdr; 116 117bail: 118 uv_dlclose(&lib); 119 120 return NULL; 121} 122 123int 124lws_plat_destroy_dl(struct lws_plugin *p) 125{ 126 uv_dlclose(&p->u.lib); 127 128 return 0; 129} 130 131#endif 132 133/* 134 * Specifically for protocol plugins support 135 */ 136 137#if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0) 138 139static int 140protocol_plugin_cb(struct lws_plugin *pin, void *each_user) 141{ 142 struct lws_context *context = (struct lws_context *)each_user; 143 const lws_plugin_protocol_t *plpr = 144 (const lws_plugin_protocol_t *)pin->hdr; 145 146 context->plugin_protocol_count += plpr->count_protocols; 147 context->plugin_extension_count += plpr->count_extensions; 148 149 return 0; 150} 151#endif 152 153int 154lws_plat_plugins_init(struct lws_context *context, const char * const *d) 155{ 156#if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0) 157 if (info->plugin_dirs) { 158 uv_loop_init(&context->uv.loop); 159 lws_plugins_init(&context->plugin_list, info->plugin_dirs, 160 "lws_protocol_plugin", NULL, 161 protocol_plugin_cb, context); 162 } 163#endif 164 165 return 0; 166} 167 168int 169lws_plat_plugins_destroy(struct lws_context * context) 170{ 171#if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0) 172 if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV) && 173 context->plugin_list) { 174 lws_plugins_destroy(&context->plugin_list, NULL, NULL); 175 while (uv_loop_close(&context->uv.loop)) 176 ; 177 } 178#endif 179 180 return 0; 181} 182