From 2e11efa84ba04e20ac8876eb6d8cf80d8e00a908 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 12 Feb 2017 18:15:15 +0800 Subject: [PATCH] file_ops: add compression flags and convert open flags to pointer ihttps://libwebsockets.org/pipermail/libwebsockets/2017-February/003127.html --- lib/libwebsockets.h | 15 ++++++++++++--- lib/lws-plat-mbed3.c | 2 +- lib/lws-plat-optee.c | 2 +- lib/lws-plat-unix.c | 4 ++-- lib/lws-plat-win.c | 4 ++-- lib/server.c | 23 ++++++++++++++++++++--- test-server/test-server-libev.c | 2 +- test-server/test-server.c | 2 +- 8 files changed, 40 insertions(+), 14 deletions(-) diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 70c9fbe..ed55bd7 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -4181,12 +4181,21 @@ lws_cgi_kill(struct lws *wsi); #define LWS_FOP_READ read #define LWS_FOP_WRITE write +#define LWS_FOP_FLAGS_MASK ((1 << 23) - 1) +#define LWS_FOP_FLAG_COMPR_ACCEPTABLE_GZIP (1 << 24) +#define LWS_FOP_FLAG_COMPR_IS_GZIP (1 << 25) + struct lws_plat_file_ops { lws_filefd_type (*LWS_FOP_OPEN)(struct lws *wsi, const char *filename, - unsigned long *filelen, int flags); + unsigned long *filelen, int *flags); /**< Open file (always binary access if plat supports it) * filelen is filled on exit to be the length of the file - * flags should be set to O_RDONLY or O_RDWR */ + * *flags & LWS_FOP_FLAGS_MASK should be set to O_RDONLY or O_RDWR. + * If the file may be gzip-compressed, + * LWS_FOP_FLAG_COMPR_ACCEPTABLE_GZIP is set. If it actually is + * gzip-compressed, then the open handler should OR + * LWS_FOP_FLAG_COMPR_IS_GZIP on to *flags before returning. + */ int (*LWS_FOP_CLOSE)(struct lws *wsi, lws_filefd_type fd); /**< close file */ unsigned long (*LWS_FOP_SEEK_CUR)(struct lws *wsi, lws_filefd_type fd, @@ -4223,7 +4232,7 @@ lws_get_fops(struct lws_context *context); */ static LWS_INLINE lws_filefd_type LWS_WARN_UNUSED_RESULT lws_plat_file_open(struct lws *wsi, const char *filename, - unsigned long *filelen, int flags) + unsigned long *filelen, int *flags) { return lws_get_fops(lws_get_context(wsi))->LWS_FOP_OPEN(wsi, filename, filelen, flags); diff --git a/lib/lws-plat-mbed3.c b/lib/lws-plat-mbed3.c index 4065099..f1ef289 100644 --- a/lib/lws-plat-mbed3.c +++ b/lib/lws-plat-mbed3.c @@ -167,7 +167,7 @@ delete_from_fd(struct lws_context *context, lws_sockfd_type fd) static lws_filefd_type _lws_plat_file_open(struct lws *wsi, const char *filename, - unsigned long *filelen, int flags) + unsigned long *filelen, int *flags) { (void)wsi; (void)filename; diff --git a/lib/lws-plat-optee.c b/lib/lws-plat-optee.c index a480789..ca7e88d 100644 --- a/lib/lws-plat-optee.c +++ b/lib/lws-plat-optee.c @@ -263,7 +263,7 @@ lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt) static lws_filefd_type _lws_plat_file_open(struct lws *wsi, const char *filename, - unsigned long *filelen, int flags) + unsigned long *filelen, int *flags) { return 0; } diff --git a/lib/lws-plat-unix.c b/lib/lws-plat-unix.c index 2625ed8..92d44c9 100644 --- a/lib/lws-plat-unix.c +++ b/lib/lws-plat-unix.c @@ -611,10 +611,10 @@ lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt) static lws_filefd_type _lws_plat_file_open(struct lws *wsi, const char *filename, - unsigned long *filelen, int flags) + unsigned long *filelen, int *flags) { struct stat stat_buf; - int ret = open(filename, flags, 0664); + int ret = open(filename, (*flags) & LWS_FOP_FLAGS_MASK, 0664); if (ret < 0) return LWS_INVALID_FILE; diff --git a/lib/lws-plat-win.c b/lib/lws-plat-win.c index aabd4b7..7327ab8 100644 --- a/lib/lws-plat-win.c +++ b/lib/lws-plat-win.c @@ -523,14 +523,14 @@ lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt) static lws_filefd_type _lws_plat_file_open(struct lws *wsi, const char *filename, - unsigned long *filelen, int flags) + unsigned long *filelen, int *flags) { HANDLE ret; WCHAR buf[MAX_PATH]; (void)wsi; MultiByteToWideChar(CP_UTF8, 0, filename, -1, buf, ARRAY_SIZE(buf)); - if ((flags & 7) == _O_RDONLY) { + if (((*flags) & 7) == _O_RDONLY) { ret = CreateFileW(buf, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); } else { diff --git a/lib/server.c b/lib/server.c index 82add22..d8ac711 100644 --- a/lib/server.c +++ b/lib/server.c @@ -2143,14 +2143,21 @@ lws_serve_http_file(struct lws *wsi, const char *file, const char *content_type, unsigned char *p = response; unsigned char *end = p + context->pt_serv_buf_size - LWS_PRE; unsigned long computed_total_content_length; - int ret = 0, cclen = 8, n = HTTP_STATUS_OK; + int ret = 0, cclen = 8, n = HTTP_STATUS_OK, fflags = O_RDONLY; #if defined(LWS_WITH_RANGES) int ranges; #endif - wsi->u.http.fd = lws_plat_file_open(wsi, file, &wsi->u.http.filelen, - O_RDONLY); + if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_ACCEPT_ENCODING)) + if (strstr("gzip", lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_ACCEPT_ENCODING)) && + strstr("deflate", lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_ACCEPT_ENCODING))) { + lwsl_debug("client indicates GZIP is acceptable\n"); + fflags |= LWS_FOP_FLAG_COMPR_ACCEPTABLE_GZIP; + } + + wsi->u.http.fd = lws_plat_file_open(wsi, file, &wsi->u.http.filelen, + &fflags); if (wsi->u.http.fd == LWS_INVALID_FILE) { lwsl_err("Unable to open '%s'\n", file); @@ -2158,6 +2165,16 @@ lws_serve_http_file(struct lws *wsi, const char *file, const char *content_type, } computed_total_content_length = wsi->u.http.filelen; + if ((fflags & (LWS_FOP_FLAG_COMPR_ACCEPTABLE_GZIP | + LWS_FOP_FLAG_COMPR_IS_GZIP)) == + (LWS_FOP_FLAG_COMPR_ACCEPTABLE_GZIP | LWS_FOP_FLAG_COMPR_IS_GZIP)) { + if (lws_add_http_header_by_token(wsi, + WSI_TOKEN_HTTP_CONTENT_ENCODING, + (unsigned char *)"gzip, deflate", 13, &p, end)) + return -1; + lwsl_debug("file is being provided in gzip\n"); + } + #if defined(LWS_WITH_RANGES) ranges = lws_ranges_init(wsi, rp, wsi->u.http.filelen); diff --git a/test-server/test-server-libev.c b/test-server/test-server-libev.c index e7a2c9d..5dc25ed 100644 --- a/test-server/test-server-libev.c +++ b/test-server/test-server-libev.c @@ -157,7 +157,7 @@ static const struct lws_extension exts[] = { */ static lws_filefd_type test_server_fops_open(struct lws *wsi, const char *filename, - unsigned long *filelen, int flags) + unsigned long *filelen, int *flags) { lws_filefd_type n; diff --git a/test-server/test-server.c b/test-server/test-server.c index 877e8ad..af28e7e 100644 --- a/test-server/test-server.c +++ b/test-server/test-server.c @@ -128,7 +128,7 @@ static struct lws_protocols protocols[] = { */ static lws_filefd_type test_server_fops_open(struct lws *wsi, const char *filename, - unsigned long *filelen, int flags) + unsigned long *filelen, int *flags) { lws_filefd_type n; -- 2.7.4