diff --git a/lib/context.c b/lib/context.c index d35b4691..668d16b9 100644 --- a/lib/context.c +++ b/lib/context.c @@ -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 = diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index cdc6c282..eebbe36b 100755 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -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 * diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 9d69dd7d..cf15ad11 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -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 diff --git a/lib/lws-plat-esp32.c b/lib/lws-plat-esp32.c index bf550be5..680dc560 100644 --- a/lib/lws-plat-esp32.c +++ b/lib/lws-plat-esp32.c @@ -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); diff --git a/lib/lws-plat-optee.c b/lib/lws-plat-optee.c index c6d42b53..f6051d09 100644 --- a/lib/lws-plat-optee.c +++ b/lib/lws-plat-optee.c @@ -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); diff --git a/lib/lws-plat-unix.c b/lib/lws-plat-unix.c index ae829414..4ab2eea4 100644 --- a/lib/lws-plat-unix.c +++ b/lib/lws-plat-unix.c @@ -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); diff --git a/lib/lws-plat-win.c b/lib/lws-plat-win.c index 98f420a4..117b69f2 100644 --- a/lib/lws-plat-win.c +++ b/lib/lws-plat-win.c @@ -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); diff --git a/lib/output.c b/lib/output.c index 09ceecc3..232246fb 100644 --- a/lib/output.c +++ b/lib/output.c @@ -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"); diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index 8d94c0db..e55c7f87 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -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 diff --git a/lib/server.c b/lib/server.c index ddf72280..61eebda3 100644 --- a/lib/server.c +++ b/lib/server.c @@ -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) { diff --git a/test-server/test-server-http.c b/test-server/test-server-http.c index c51b41e9..154674b9 100644 --- a/test-server/test-server-http.c +++ b/test-server/test-server-http.c @@ -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; diff --git a/test-server/test-server.c b/test-server/test-server.c index 1eb4bec1..93fb116d 100644 --- a/test-server/test-server.c +++ b/test-server/test-server.c @@ -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)