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 
36 const lws_plugin_header_t *
lws_plat_dlopen(struct lws_plugin **pplugin, const char *libpath, const char *sofilename, const char *_class, each_plugin_cb_t each, void *each_user)37 lws_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 
117 bail:
118 	uv_dlclose(&lib);
119 
120 	return NULL;
121 }
122 
123 int
lws_plat_destroy_dl(struct lws_plugin *p)124 lws_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 
139 static int
protocol_plugin_cb(struct lws_plugin *pin, void *each_user)140 protocol_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 
153 int
lws_plat_plugins_init(struct lws_context *context, const char * const *d)154 lws_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 
168 int
lws_plat_plugins_destroy(struct lws_context * context)169 lws_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