mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
lws_dir: wrap dir scanning backend and convert lejp-conf
We use POSIX dir scanning apis normally, but for windows, we require libuv to do it for us. Formalize that into a wrapper lws_dir() that hides the backend code. Make it configurable, ON by default and forced on with lejp-conf that depends on it.
This commit is contained in:
parent
5d1cd3cb4b
commit
119aa5c0ad
5 changed files with 222 additions and 88 deletions
|
@ -103,6 +103,11 @@ option(LWS_WITH_LEJP "With the Lightweight JSON Parser" ON)
|
|||
option(LWS_WITH_LEJP_CONF "With LEJP configuration parser as used by lwsws" ON)
|
||||
option(LWS_WITH_SQLITE3 "Require SQLITE3 support" OFF)
|
||||
option(LWS_WITH_SMTP "Provide SMTP support" OFF)
|
||||
if (WIN32 OR LWS_WITH_ESP32)
|
||||
option(LWS_WITH_DIR "Directory scanning api support" OFF)
|
||||
else()
|
||||
option(LWS_WITH_DIR "Directory scanning api support" ON)
|
||||
endif()
|
||||
option(LWS_WITH_NO_LOGS "Disable all logging from being compiled in" OFF)
|
||||
option(LWS_AVOID_SIGPIPE_IGN "Android 7+ reportedly needs this" OFF)
|
||||
option(LWS_WITH_STATS "Keep statistics of lws internal operations" OFF)
|
||||
|
@ -293,7 +298,6 @@ if (NOT LWS_ROLE_WS)
|
|||
set(LWS_WITHOUT_EXTENSIONS 1)
|
||||
endif()
|
||||
|
||||
|
||||
include_directories(include plugins)
|
||||
|
||||
|
||||
|
@ -378,11 +382,13 @@ set(LWS_MAX_SMP 1)
|
|||
set(LWS_WITH_THREADPOOL 0)
|
||||
endif()
|
||||
|
||||
|
||||
if (LWS_WITHOUT_SERVER)
|
||||
set(LWS_WITH_LWSWS OFF)
|
||||
endif()
|
||||
|
||||
if (LWS_WITH_LEJP_CONF)
|
||||
set(LWS_WITH_DIR 1)
|
||||
endif()
|
||||
|
||||
# confirm H1 relationships
|
||||
|
||||
|
@ -913,6 +919,10 @@ if (LWS_WITH_NETWORK)
|
|||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (LWS_WITH_DIR)
|
||||
list(APPEND SOURCES lib/misc/dir.c)
|
||||
endif()
|
||||
|
||||
if (LWS_WITH_THREADPOOL AND UNIX AND LWS_HAVE_PTHREAD_H)
|
||||
list(APPEND SOURCES lib/misc/threadpool/threadpool.c)
|
||||
|
|
|
@ -81,6 +81,7 @@
|
|||
#cmakedefine LWS_WITH_BORINGSSL
|
||||
#cmakedefine LWS_WITH_CGI
|
||||
#cmakedefine LWS_WITH_CUSTOM_HEADERS
|
||||
#cmakedefine LWS_WITH_DIR
|
||||
#cmakedefine LWS_WITH_ESP32
|
||||
#cmakedefine LWS_WITH_FTS
|
||||
#cmakedefine LWS_WITH_GENCRYPTO
|
||||
|
|
|
@ -677,7 +677,43 @@ lws_rx_flow_allow_all_protocol(const struct lws_context *context,
|
|||
LWS_VISIBLE LWS_EXTERN size_t
|
||||
lws_remaining_packet_payload(struct lws *wsi);
|
||||
|
||||
#if defined(LWS_WITH_DIR)
|
||||
|
||||
typedef enum {
|
||||
LDOT_UNKNOWN,
|
||||
LDOT_FILE,
|
||||
LDOT_DIR,
|
||||
LDOT_LINK,
|
||||
LDOT_FIFO,
|
||||
LDOTT_SOCKET,
|
||||
LDOT_CHAR,
|
||||
LDOT_BLOCK
|
||||
} lws_dir_obj_type_t;
|
||||
|
||||
struct lws_dir_entry {
|
||||
const char *name;
|
||||
lws_dir_obj_type_t type;
|
||||
};
|
||||
|
||||
typedef int
|
||||
lws_dir_callback_function(const char *dirpath, void *user,
|
||||
struct lws_dir_entry *lde);
|
||||
|
||||
/**
|
||||
* lws_dir() - get a callback for everything in a directory
|
||||
*
|
||||
* \param dirpath: the directory to scan
|
||||
* \param user: pointer to give to callback
|
||||
* \param cb: callback to receive information on each file or dir
|
||||
*
|
||||
* Calls \p cb (with \p user) for every object in dirpath.
|
||||
*
|
||||
* This wraps whether it's using POSIX apis, or libuv (as needed for windows,
|
||||
* since it refuses to support POSIX apis for this).
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* lws_is_ssl() - Find out if connection is using SSL
|
||||
|
|
143
lib/misc/dir.c
Normal file
143
lib/misc/dir.c
Normal file
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Lws directory scan wrapper
|
||||
*
|
||||
* Copyright (C) 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation:
|
||||
* version 2.1 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <libwebsockets.h>
|
||||
#include "core/private.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(LWS_WITH_LIBUV) && UV_VERSION_MAJOR > 0
|
||||
|
||||
int
|
||||
lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb)
|
||||
{
|
||||
struct lws_dir_entry lde;
|
||||
uv_dirent_t dent;
|
||||
uv_fs_t req;
|
||||
int ret = 1, ir;
|
||||
uv_loop_t loop;
|
||||
|
||||
ir = uv_loop_init(&loop);
|
||||
if (ir) {
|
||||
lwsl_err("%s: loop init failed %d\n", __func__, ir);
|
||||
}
|
||||
|
||||
ir = uv_fs_scandir(&loop, &req, dirpath, 0, NULL);
|
||||
if (ir < 0) {
|
||||
lwsl_err("Scandir on %s failed, errno %d\n", dirpath, LWS_ERRNO);
|
||||
return 2;
|
||||
}
|
||||
|
||||
while (uv_fs_scandir_next(&req, &dent) != UV_EOF) {
|
||||
lde.name = dent.name;
|
||||
lde.type = (int)dent.type;
|
||||
if (cb(dirpath, user, &lde))
|
||||
goto bail;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
bail:
|
||||
uv_fs_req_cleanup(&req);
|
||||
while (uv_loop_close(&loop))
|
||||
;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#if !defined(_WIN32) && !defined(LWS_WITH_ESP32)
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
static int filter(const struct dirent *ent)
|
||||
{
|
||||
if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb)
|
||||
{
|
||||
struct lws_dir_entry lde;
|
||||
struct dirent **namelist;
|
||||
int n, i, ret = 1;
|
||||
|
||||
n = scandir((char *)dirpath, &namelist, filter, alphasort);
|
||||
if (n < 0) {
|
||||
lwsl_err("Scandir on '%s' failed, errno %d\n", dirpath, LWS_ERRNO);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (strchr(namelist[i]->d_name, '~'))
|
||||
goto skip;
|
||||
lde.name = namelist[i]->d_name;
|
||||
switch (namelist[i]->d_type) {
|
||||
case DT_BLK:
|
||||
lde.type = LDOT_BLOCK;
|
||||
break;
|
||||
case DT_CHR:
|
||||
lde.type = LDOT_CHAR;
|
||||
break;
|
||||
case DT_DIR:
|
||||
lde.type = LDOT_DIR;
|
||||
break;
|
||||
case DT_FIFO:
|
||||
lde.type = LDOT_FIFO;
|
||||
break;
|
||||
case DT_LNK:
|
||||
lde.type = LDOT_LINK;
|
||||
break;
|
||||
case DT_REG:
|
||||
lde.type = LDOT_FILE;
|
||||
break;
|
||||
case DT_SOCK:
|
||||
lde.type = LDOTT_SOCKET;
|
||||
break;
|
||||
default:
|
||||
lde.type = LDOT_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
if (cb(dirpath, user, &lde)) {
|
||||
while (i++ < n)
|
||||
free(namelist[i]);
|
||||
goto bail;
|
||||
}
|
||||
skip:
|
||||
free(namelist[i]);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
bail:
|
||||
free(namelist);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
#error "If you want lws_dir onw windows, you need libuv"
|
||||
#endif
|
||||
#endif
|
|
@ -893,100 +893,34 @@ lwsws_get_config(void *user, const char *f, const char * const *paths,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(LWS_WITH_LIBUV) && UV_VERSION_MAJOR > 0
|
||||
struct lws_dir_args {
|
||||
void *user;
|
||||
const char * const *paths;
|
||||
int count_paths;
|
||||
lejp_callback cb;
|
||||
};
|
||||
|
||||
static int
|
||||
lwsws_get_config_d(void *user, const char *d, const char * const *paths,
|
||||
int count_paths, lejp_callback cb)
|
||||
lwsws_get_config_d_cb(const char *dirpath, void *user,
|
||||
struct lws_dir_entry *lde)
|
||||
{
|
||||
uv_dirent_t dent;
|
||||
uv_fs_t req;
|
||||
struct lws_dir_args *da = (struct lws_dir_args *)user;
|
||||
char path[256];
|
||||
int ret = 0, ir;
|
||||
uv_loop_t loop;
|
||||
|
||||
ir = uv_loop_init(&loop);
|
||||
if (ir) {
|
||||
lwsl_err("%s: loop init failed %d\n", __func__, ir);
|
||||
}
|
||||
|
||||
if (!uv_fs_scandir(&loop, &req, d, 0, NULL)) {
|
||||
lwsl_err("Scandir on %s failed\n", d);
|
||||
return 2;
|
||||
}
|
||||
|
||||
while (uv_fs_scandir_next(&req, &dent) != UV_EOF) {
|
||||
lws_snprintf(path, sizeof(path) - 1, "%s/%s", d, dent.name);
|
||||
ret = lwsws_get_config(user, path, paths, count_paths, cb);
|
||||
if (ret)
|
||||
goto bail;
|
||||
}
|
||||
|
||||
bail:
|
||||
uv_fs_req_cleanup(&req);
|
||||
while (uv_loop_close(&loop))
|
||||
;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#ifndef _WIN32
|
||||
static int filter(const struct dirent *ent)
|
||||
{
|
||||
if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
|
||||
if (lde->type != LDOT_FILE)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
lws_snprintf(path, sizeof(path) - 1, "%s/%s", dirpath, lde->name);
|
||||
|
||||
return lwsws_get_config(da->user, path, da->paths,
|
||||
da->count_paths, da->cb);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
lwsws_get_config_d(void *user, const char *d, const char * const *paths,
|
||||
int count_paths, lejp_callback cb)
|
||||
{
|
||||
#if !defined(_WIN32) && !defined(LWS_WITH_ESP32)
|
||||
struct dirent **namelist;
|
||||
char path[256];
|
||||
int n, i, ret = 0;
|
||||
|
||||
n = scandir((char *) d, &namelist, filter, alphasort);
|
||||
if (n < 0) {
|
||||
lwsl_err("Scandir on %s failed\n", d);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (strchr(namelist[i]->d_name, '~'))
|
||||
goto skip;
|
||||
lws_snprintf(path, sizeof(path) - 1, "%s/%s", d,
|
||||
namelist[i]->d_name);
|
||||
ret = lwsws_get_config(user, path, paths, count_paths, cb);
|
||||
if (ret) {
|
||||
while (i++ < n)
|
||||
free(namelist[i]);
|
||||
goto bail;
|
||||
}
|
||||
skip:
|
||||
free(namelist[i]);
|
||||
}
|
||||
|
||||
bail:
|
||||
free(namelist);
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int
|
||||
lwsws_get_config_globals(struct lws_context_creation_info *info, const char *d,
|
||||
char **cs, int *len)
|
||||
{
|
||||
struct lws_dir_args da;
|
||||
struct jpargs a;
|
||||
const char * const *old = info->plugin_dirs;
|
||||
char dd[128];
|
||||
|
@ -1015,9 +949,13 @@ lwsws_get_config_globals(struct lws_context_creation_info *info, const char *d,
|
|||
LWS_ARRAY_SIZE(paths_global), lejp_globals_cb) > 1)
|
||||
return 1;
|
||||
lws_snprintf(dd, sizeof(dd) - 1, "%s/conf.d", d);
|
||||
if (lwsws_get_config_d(&a, dd, paths_global,
|
||||
LWS_ARRAY_SIZE(paths_global),
|
||||
lejp_globals_cb) > 1)
|
||||
|
||||
da.user = &a;
|
||||
da.paths = paths_global;
|
||||
da.count_paths = LWS_ARRAY_SIZE(paths_global),
|
||||
da.cb = lejp_globals_cb;
|
||||
|
||||
if (lws_dir(dd, &da, lwsws_get_config_d_cb) > 1)
|
||||
return 1;
|
||||
|
||||
a.plugin_dirs[a.count_plugin_dirs] = NULL;
|
||||
|
@ -1033,6 +971,7 @@ lwsws_get_config_vhosts(struct lws_context *context,
|
|||
struct lws_context_creation_info *info, const char *d,
|
||||
char **cs, int *len)
|
||||
{
|
||||
struct lws_dir_args da;
|
||||
struct jpargs a;
|
||||
char dd[128];
|
||||
|
||||
|
@ -1052,8 +991,13 @@ lwsws_get_config_vhosts(struct lws_context *context,
|
|||
LWS_ARRAY_SIZE(paths_vhosts), lejp_vhosts_cb) > 1)
|
||||
return 1;
|
||||
lws_snprintf(dd, sizeof(dd) - 1, "%s/conf.d", d);
|
||||
if (lwsws_get_config_d(&a, dd, paths_vhosts,
|
||||
LWS_ARRAY_SIZE(paths_vhosts), lejp_vhosts_cb) > 1)
|
||||
|
||||
da.user = &a;
|
||||
da.paths = paths_vhosts;
|
||||
da.count_paths = LWS_ARRAY_SIZE(paths_vhosts),
|
||||
da.cb = lejp_vhosts_cb;
|
||||
|
||||
if (lws_dir(dd, &da, lwsws_get_config_d_cb) > 1)
|
||||
return 1;
|
||||
|
||||
*cs = a.p;
|
||||
|
|
Loading…
Add table
Reference in a new issue