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_...
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 =
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);
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];
}
/**
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 *
#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
* 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
*
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)
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);
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
*
* 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);
* \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);
}
* \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);
}
* \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);
* \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
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)
{
return NULL;
}
-static int
+LWS_VISIBLE int
_lws_plat_file_close(lws_fop_fd_t fops_fd)
{
int fd = fops_fd->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)
{
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)
{
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);
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)
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)
{
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)
{
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);
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);
return NULL;
}
-static int
+LWS_VISIBLE int
_lws_plat_file_close(lws_fop_fd_t fop_fd)
{
int fd = fop_fd->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)
{
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)
{
}
}
- 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);
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)
{
return NULL;
}
-static int
+LWS_VISIBLE int
_lws_plat_file_close(lws_fop_fd_t fop_fd)
{
HANDLE fd = fop_fd->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)
{
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)
{
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);
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;
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);
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;
{
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");
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
}
- 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) {
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) {
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;
}
/*
/* 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) {
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;
* 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)