1
0
Fork 0
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:
Andy Green 2019-03-14 08:24:40 +08:00
parent 5d1cd3cb4b
commit 119aa5c0ad
5 changed files with 222 additions and 88 deletions

View file

@ -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)

View file

@ -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

View file

@ -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
View 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

View file

@ -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;