fops: allow setting from context creation and introduce lws_select_fops_by_vfs_path

1) There's now a .fops pointer that can be set in the context creation info.  If set, the array of
fops it points to (terminated by an entry with .open = NULL) is walked to find out the best vfs filesystem
path match (comparing the vfs path to fops.path_prefix) for which fops to use.

If none given (.fops is NULL in info) then behaviour is as before, fops are the platform-provided one only.

2) The built in fileserving now walks any array of fops looking for the best fops match automatically.

3) lws_plat_file_... apis are renamed to lws_vfs_file_...
This commit is contained in:
Andy Green 2017-03-01 14:28:56 +08:00
parent be8d791b5e
commit 1ada132932
12 changed files with 119 additions and 70 deletions

View file

@ -619,6 +619,23 @@ lws_create_context(struct lws_context_creation_info *info)
else
context->pt_serv_buf_size = 4096;
/* default to just the platform fops implementation */
context->fops_default[0].open = _lws_plat_file_open;
context->fops_default[0].close = _lws_plat_file_close;
context->fops_default[0].seek_cur = _lws_plat_file_seek_cur;
context->fops_default[0].read = _lws_plat_file_read;
context->fops_default[0].write = _lws_plat_file_write;
context->fops_default[0].path_prefix = "/";
// context->fops_default[1].open is already NULL from zalloc
/* it can be overridden from context creation info */
if (info->fops)
context->fops = info->fops;
else
context->fops = &context->fops_default[0];
context->reject_service_keywords = info->reject_service_keywords;
if (info->external_baggage_free_on_destroy)
context->external_baggage_free_on_destroy =

View file

@ -239,7 +239,7 @@ lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
if (wsi->mode == LWSCM_HTTP_SERVING_ACCEPTED &&
wsi->u.http.fop_fd != NULL) {
lws_plat_file_close(wsi->u.http.fop_fd);
lws_vfs_file_close(wsi->u.http.fop_fd);
wsi->u.http.fop_fd = NULL;
wsi->vhost->protocols->callback(wsi,
LWS_CALLBACK_CLOSED_HTTP, wsi->user_space, NULL, 0);
@ -960,7 +960,30 @@ lws_callback_vhost_protocols(struct lws *wsi, int reason, void *in, int len)
LWS_VISIBLE LWS_EXTERN void
lws_set_fops(struct lws_context *context, struct lws_plat_file_ops *fops)
{
memcpy(&context->fops, fops, sizeof *fops);
memcpy(&context->fops_default, fops, sizeof *fops);
}
LWS_VISIBLE LWS_EXTERN const struct lws_plat_file_ops *
lws_select_fops_by_vfs_path(const struct lws_context *context, const char *vfs_path)
{
const struct lws_plat_file_ops *fops = context->fops;
int hit = -1, n = 0, matchlen = 0, len;
while (fops->open) {
len = strlen(fops->path_prefix);
if (!strncmp(vfs_path, fops->path_prefix, len))
if (len > matchlen) {
hit = n;
matchlen = len;
}
fops++;
}
if (hit < 0)
return context->fops_default;
return &context->fops[hit];
}
/**
@ -1362,7 +1385,7 @@ lws_union_transition(struct lws *wsi, enum connection_mode mode)
LWS_VISIBLE struct lws_plat_file_ops *
lws_get_fops(struct lws_context *context)
{
return &context->fops;
return &context->fops_default[0];
}
LWS_VISIBLE LWS_EXTERN struct lws_context *

View file

@ -1612,6 +1612,8 @@ enum lws_context_options {
#define lws_check_opt(c, f) (((c) & (f)) == (f))
struct lws_plat_file_ops;
/** struct lws_context_creation_info - parameters to create context and /or vhost with
*
* This is also used to create vhosts.... if LWS_SERVER_OPTION_EXPLICIT_VHOSTS
@ -1809,6 +1811,16 @@ struct lws_context_creation_info {
* or you can leave it as NULL to get "DEFAULT" */
#endif
const struct lws_plat_file_ops *fops;
/**< CONTEXT: NULL, or pointer to an array of fops structs, terminated
* by a sentinel with NULL .open.
*
* If NULL, lws provides just the platform file operations struct for
* backwards compatibility. If set to point to an array of fops
* structs, lws_select_fops_by_vfs_path() will select the best match
* comparing the left of vfs_path to each fops .path_prefix.
*/
/* Add new things just above here ---^
* This is part of the ABI, don't needlessly break compatibility
*
@ -4271,7 +4283,7 @@ lws_cgi_kill(struct lws *wsi);
struct lws_plat_file_ops;
struct lws_fop_fd {
lws_filefd_type fd;
struct lws_plat_file_ops *fops;
const struct lws_plat_file_ops *fops;
void *filesystem_priv;
};
#if defined(WIN32) || defined(_WIN32)
@ -4289,7 +4301,7 @@ typedef ssize_t lws_fileofs_t;
typedef uint32_t lws_fop_flags_t;
struct lws_plat_file_ops {
lws_fop_fd_t (*LWS_FOP_OPEN)(struct lws_plat_file_ops *fops,
lws_fop_fd_t (*LWS_FOP_OPEN)(const struct lws_plat_file_ops *fops,
const char *filename,
lws_filepos_t *filelen,
lws_fop_flags_t *flags);
@ -4328,6 +4340,8 @@ LWS_VISIBLE LWS_EXTERN struct lws_plat_file_ops * LWS_WARN_UNUSED_RESULT
lws_get_fops(struct lws_context *context);
LWS_VISIBLE LWS_EXTERN void
lws_set_fops(struct lws_context *context, struct lws_plat_file_ops *fops);
LWS_VISIBLE LWS_EXTERN const struct lws_plat_file_ops * LWS_WARN_UNUSED_RESULT
lws_select_fops_by_vfs_path(const struct lws_context *context, const char *vfs_path);
/**
* lws_plat_file_open() - file open operations
*
@ -4339,7 +4353,7 @@ lws_set_fops(struct lws_context *context, struct lws_plat_file_ops *fops);
* returns semi-opaque handle
*/
static LWS_INLINE lws_fop_fd_t LWS_WARN_UNUSED_RESULT
lws_plat_file_open(struct lws_plat_file_ops *fops, const char *filename,
lws_vfs_file_open(const struct lws_plat_file_ops *fops, const char *filename,
lws_filepos_t *filelen, lws_fop_flags_t *flags)
{
return fops->LWS_FOP_OPEN(fops, filename, filelen, flags);
@ -4351,7 +4365,7 @@ lws_plat_file_open(struct lws_plat_file_ops *fops, const char *filename,
* \param fop_fd: file handle to close
*/
static LWS_INLINE int
lws_plat_file_close(lws_fop_fd_t fop_fd)
lws_vfs_file_close(lws_fop_fd_t fop_fd)
{
return fop_fd->fops->LWS_FOP_CLOSE(fop_fd);
}
@ -4364,7 +4378,7 @@ lws_plat_file_close(lws_fop_fd_t fop_fd)
* \param offset: position to seek to
*/
static LWS_INLINE lws_fileofs_t
lws_plat_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset)
lws_vfs_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset)
{
return fop_fd->fops->LWS_FOP_SEEK_CUR(fop_fd, offset);
}
@ -4377,7 +4391,7 @@ lws_plat_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset)
* \param len: max length
*/
static LWS_INLINE int LWS_WARN_UNUSED_RESULT
lws_plat_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
lws_vfs_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
uint8_t *buf, lws_filepos_t len)
{
return fop_fd->fops->LWS_FOP_READ(fop_fd, amount, buf, len);
@ -4391,11 +4405,30 @@ lws_plat_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
* \param len: max length
*/
static LWS_INLINE int LWS_WARN_UNUSED_RESULT
lws_plat_file_write(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
lws_vfs_file_write(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
uint8_t *buf, lws_filepos_t len)
{
return fop_fd->fops->LWS_FOP_WRITE(fop_fd, amount, buf, len);
}
/* these are the flatform file operations implmenetations... they can
* be called directly and used in fops arrays
*/
LWS_VISIBLE LWS_EXTERN lws_fop_fd_t
_lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
lws_filepos_t *filelen, lws_fop_flags_t *flags);
LWS_VISIBLE LWS_EXTERN int
_lws_plat_file_close(lws_fop_fd_t fop_fd);
LWS_VISIBLE LWS_EXTERN lws_fileofs_t
_lws_plat_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset);
LWS_VISIBLE LWS_EXTERN int
_lws_plat_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
uint8_t *buf, lws_filepos_t len);
LWS_VISIBLE LWS_EXTERN int
_lws_plat_file_write(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
uint8_t *buf, lws_filepos_t len);
//@}
/** \defgroup smtp

View file

@ -395,7 +395,7 @@ lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt)
return inet_ntop(af, src, dst, cnt);
}
static lws_fop_fd_t
LWS_VISIBLE lws_fop_fd_t
_lws_plat_file_open(struct lws_plat_file_ops *fops, const char *filename,
lws_filepos_t *filelen, lws_fop_flags_t *flags)
{
@ -426,7 +426,7 @@ bail:
return NULL;
}
static int
LWS_VISIBLE int
_lws_plat_file_close(lws_fop_fd_t fops_fd)
{
int fd = fops_fd->fd;
@ -436,13 +436,13 @@ _lws_plat_file_close(lws_fop_fd_t fops_fd)
return close(fd);
}
lws_fileofs_t
LWS_VISIBLE lws_fileofs_t
_lws_plat_file_seek_cur(lws_fop_fd_t fops_fd, lws_fileofs_t offset)
{
return lseek(fops_fd->fd, offset, SEEK_CUR);
}
static int
LWS_VISIBLE int
_lws_plat_file_read(lws_fop_fd_t fops_fd, lws_filepos_t *amount,
uint8_t *buf, lws_filepos_t len)
{
@ -459,7 +459,7 @@ _lws_plat_file_read(lws_fop_fd_t fops_fd, lws_filepos_t *amount,
return 0;
}
static int
LWS_VISIBLE int
_lws_plat_file_write(lws_fop_fd_t fops_fd, lws_filepos_t *amount,
uint8_t *buf, lws_filepos_t len)
{
@ -493,12 +493,6 @@ lws_plat_init(struct lws_context *context,
lwsl_notice(" mem: platform fd map: %5lu bytes\n",
(unsigned long)(sizeof(struct lws *) * context->max_fds));
context->fops.LWS_FOP_OPEN = _lws_plat_file_open;
context->fops.LWS_FOP_CLOSE = _lws_plat_file_close;
context->fops.LWS_FOP_SEEK_CUR = _lws_plat_file_seek_cur;
context->fops.LWS_FOP_READ = _lws_plat_file_read;
context->fops.LWS_FOP_WRITE = _lws_plat_file_write;
#ifdef LWS_WITH_PLUGINS
if (info->plugin_dirs)
lws_plat_plugins_init(context, info->plugin_dirs);

View file

@ -261,7 +261,7 @@ lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt)
return "lws_plat_inet_ntop";
}
static lws_fop_fd_t
LWS_VISIBLE lws_fop_fd_t
_lws_plat_file_open(lws_plat_file_open(struct lws_plat_file_ops *fops,
const char *filename, lws_filepos_t *filelen,
lws_fop_flags_t *flags)
@ -269,19 +269,19 @@ _lws_plat_file_open(lws_plat_file_open(struct lws_plat_file_ops *fops,
return NULL;
}
static int
LWS_VISIBLE int
_lws_plat_file_close(lws_fop_fd_t fop_fd)
{
return 0;
}
unsigned lws_fileofs_t
LWS_VISIBLE lws_fileofs_t
_lws_plat_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset)
{
return 0;
}
static int
LWS_VISIBLE int
_lws_plat_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
uint8_t *buf, lws_filepos_t len)
{
@ -289,7 +289,7 @@ _lws_plat_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
return 0;
}
static int
LWS_VISIBLE int
_lws_plat_file_write(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
uint8_t *buf, lws_filepos_t len)
{
@ -314,12 +314,6 @@ lws_plat_init(struct lws_context *context,
lwsl_notice(" mem: platform fd map: %5lu bytes\n",
(long)sizeof(struct lws *) * context->max_fds);
context->fops.open = _lws_plat_file_open;
context->fops.close = _lws_plat_file_close;
context->fops.seek_cur = _lws_plat_file_seek_cur;
context->fops.read = _lws_plat_file_read;
context->fops.write = _lws_plat_file_write;
#ifdef LWS_WITH_PLUGINS
if (info->plugin_dirs)
lws_plat_plugins_init(context, info->plugin_dirs);

View file

@ -609,11 +609,9 @@ lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt)
return inet_ntop(af, src, dst, cnt);
}
// lws_get_fops(lws_get_context(wsi))
static lws_fop_fd_t
_lws_plat_file_open(struct lws_plat_file_ops *fops, const char *filename,
lws_filepos_t *filelen, lws_fop_flags_t *flags)
LWS_VISIBLE lws_fop_fd_t
_lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
lws_filepos_t *filelen, lws_fop_flags_t *flags)
{
struct stat stat_buf;
int ret = open(filename, (*flags) & LWS_FOP_FLAGS_MASK, 0664);
@ -641,7 +639,7 @@ bail:
return NULL;
}
static int
LWS_VISIBLE int
_lws_plat_file_close(lws_fop_fd_t fop_fd)
{
int fd = fop_fd->fd;
@ -650,13 +648,13 @@ _lws_plat_file_close(lws_fop_fd_t fop_fd)
return close(fd);
}
lws_fileofs_t
LWS_VISIBLE lws_fileofs_t
_lws_plat_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset)
{
return lseek(fop_fd->fd, offset, SEEK_CUR);
}
static int
LWS_VISIBLE int
_lws_plat_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
uint8_t *buf, lws_filepos_t len)
{
@ -673,7 +671,7 @@ _lws_plat_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
return 0;
}
static int
LWS_VISIBLE int
_lws_plat_file_write(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
uint8_t *buf, lws_filepos_t len)
{
@ -737,12 +735,6 @@ lws_plat_init(struct lws_context *context,
}
}
context->fops.open = _lws_plat_file_open;
context->fops.close = _lws_plat_file_close;
context->fops.seek_cur = _lws_plat_file_seek_cur;
context->fops.read = _lws_plat_file_read;
context->fops.write = _lws_plat_file_write;
#ifdef LWS_WITH_PLUGINS
if (info->plugin_dirs)
lws_plat_plugins_init(context, info->plugin_dirs);

View file

@ -521,7 +521,7 @@ lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt)
return ok ? dst : NULL;
}
static lws_fop_fd_t
LWS_VISIBLE lws_fop_fd_t
_lws_plat_file_open(struct lws_plat_file_ops *fops, const char *filename,
lws_filepos_t *filelen, lws_fop_flags_t *flags)
{
@ -558,7 +558,7 @@ bail:
return NULL;
}
static int
LWS_VISIBLE int
_lws_plat_file_close(lws_fop_fd_t fop_fd)
{
HANDLE fd = fop_fd->fd;
@ -570,13 +570,13 @@ _lws_plat_file_close(lws_fop_fd_t fop_fd)
return 0;
}
static lws_fileofs_t
LWS_VISIBLE lws_fileofs_t
_lws_plat_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset)
{
return SetFilePointer((HANDLE)fop_fd->fd, offset, NULL, FILE_CURRENT);
}
static int
LWS_VISIBLE int
_lws_plat_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
uint8_t *buf, lws_filepos_t len)
{
@ -593,7 +593,7 @@ _lws_plat_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
return 0;
}
static int
LWS_VISIBLE int
_lws_plat_file_write(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
uint8_t* buf, lws_filepos_t len)
{
@ -639,12 +639,6 @@ lws_plat_init(struct lws_context *context,
context->fd_random = 0;
context->fops.open = _lws_plat_file_open;
context->fops.close = _lws_plat_file_close;
context->fops.seek_cur = _lws_plat_file_seek_cur;
context->fops.read = _lws_plat_file_read;
context->fops.write = _lws_plat_file_write;
#ifdef LWS_WITH_PLUGINS
if (info->plugin_dirs)
lws_plat_plugins_init(context, info->plugin_dirs);

View file

@ -591,7 +591,7 @@ LWS_VISIBLE int lws_serve_http_file_fragment(struct lws *wsi)
lwsl_notice("%s: doing range start %llu\n", __func__, wsi->u.http.range.start);
if ((long)lws_plat_file_seek_cur(wsi->u.http.fop_fd,
if ((long)lws_vfs_file_seek_cur(wsi->u.http.fop_fd,
wsi->u.http.range.start -
wsi->u.http.filepos) < 0)
return -1;
@ -633,7 +633,7 @@ LWS_VISIBLE int lws_serve_http_file_fragment(struct lws *wsi)
poss -= 10 + 128;
}
if (lws_plat_file_read(wsi->u.http.fop_fd, &amount, p, poss) < 0)
if (lws_vfs_file_read(wsi->u.http.fop_fd, &amount, p, poss) < 0)
return -1; /* caller will close */
//lwsl_notice("amount %ld\n", amount);
@ -700,7 +700,7 @@ LWS_VISIBLE int lws_serve_http_file_fragment(struct lws *wsi)
if (m != n) {
/* adjust for what was not sent */
if (lws_plat_file_seek_cur(wsi->u.http.fop_fd,
if (lws_vfs_file_seek_cur(wsi->u.http.fop_fd,
m - n) ==
(unsigned long)-1)
return -1;
@ -716,7 +716,7 @@ all_sent:
{
wsi->state = LWSS_HTTP;
/* we might be in keepalive, so close it off here */
lws_plat_file_close(wsi->u.http.fop_fd);
lws_vfs_file_close(wsi->u.http.fop_fd);
wsi->u.http.fop_fd = NULL;
lwsl_debug("file completed\n");

View file

@ -808,7 +808,8 @@ struct lws_context {
time_t last_timeout_check_s;
time_t last_ws_ping_pong_check_s;
time_t time_up;
struct lws_plat_file_ops fops;
const struct lws_plat_file_ops *fops;
struct lws_plat_file_ops fops_default[2];
struct lws_context_per_thread pt[LWS_MAX_SMP];
struct lws_conn_stats conn_stats;
#ifdef _WIN32

View file

@ -2227,7 +2227,8 @@ lws_serve_http_file(struct lws *wsi, const char *file, const char *content_type,
}
wsi->u.http.fop_fd = lws_plat_file_open(&wsi->context->fops, file,
wsi->u.http.fop_fd = lws_vfs_file_open(lws_select_fops_by_vfs_path(
wsi->context, file), file,
&wsi->u.http.filelen,
&fflags);
if (!wsi->u.http.fop_fd) {

View file

@ -292,7 +292,7 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
p = buffer + LWS_PRE;
end = p + sizeof(buffer) - LWS_PRE;
pss->fop_fd = lws_plat_file_open(lws_get_fops(lws_get_context(wsi)),
pss->fop_fd = lws_vfs_file_open(lws_get_fops(lws_get_context(wsi)),
leaf_path, &file_len, &flags);
if (!pss->fop_fd) {
@ -346,7 +346,7 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
p - (buffer + LWS_PRE),
LWS_WRITE_HTTP_HEADERS);
if (n < 0) {
lws_plat_file_close(pss->fop_fd);
lws_vfs_file_close(pss->fop_fd);
return -1;
}
/*
@ -555,7 +555,7 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
/* he couldn't handle that much */
n = m;
n = lws_plat_file_read(pss->fop_fd,
n = lws_vfs_file_read(pss->fop_fd,
&amount, buffer + LWS_PRE, n);
/* problem reading, close conn */
if (n < 0) {
@ -588,12 +588,12 @@ later:
lws_callback_on_writable(wsi);
break;
penultimate:
lws_plat_file_close(pss->fop_fd);
lws_vfs_file_close(pss->fop_fd);
pss->fop_fd = NULL;
goto try_to_reuse;
bail:
lws_plat_file_close(pss->fop_fd);
lws_vfs_file_close(pss->fop_fd);
return -1;

View file

@ -121,7 +121,7 @@ static struct lws_protocols protocols[] = {
* compressed files without decompressing the whole archive)
*/
static lws_fop_fd_t
test_server_fops_open(struct lws_plat_file_ops *fops,
test_server_fops_open(const struct lws_plat_file_ops *fops,
const char *filename,
lws_filepos_t *filelen,
lws_fop_flags_t *flags)