libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit 1c4f23db7458d79a04c8e68022ade67cb5ee006b
parent babda9e9c702aee6e03e7537108383e32a7c17d0
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sun, 26 Jul 2020 14:15:50 +0200

add ability to serve files from pipe

Diffstat:
MChangeLog | 4++++
Mdoc/libmicrohttpd.texi | 15+++++++++++++++
Msrc/include/microhttpd.h | 20+++++++++++++++++---
Msrc/microhttpd/connection.c | 3+++
Msrc/microhttpd/internal.h | 5+++++
Msrc/microhttpd/response.c | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 105 insertions(+), 3 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,7 @@ +Sun 26 Jul 2020 01:56:54 PM CEST + Add MHD_create_response_from_pipe() to allow creating a response based + on data read from a pipe. -CG + Fri Jul 10 15:04:51 CEST 2020 Fixed Postprocessor URL-encoded parsing if '%' fell on boundary. -CG/MD diff --git a/doc/libmicrohttpd.texi b/doc/libmicrohttpd.texi @@ -2018,6 +2018,21 @@ Return @code{NULL} on error (i.e. invalid arguments, out of memory). @end deftypefun +@deftypefun {struct MHD_Response *} MHD_create_response_from_pipe (uint64_t size, int fd) +Create a response object. The response object can be extended with +header information and then it can be used ONLY ONCE. + +@table @var +@item fd +file descriptor of the read-end of the pipe; will be +closed when response is destroyed. +The descriptor should be in blocking-IO mode. +@end table + +Return @code{NULL} on error (i.e. out of memory). +@end deftypefun + + @deftypefun {struct MHD_Response *} MHD_create_response_from_fd_at_offset (size_t size, int fd, off_t offset) Create a response object. The response object can be extended with header information and then it can be used any number of times. diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h @@ -180,7 +180,7 @@ enum MHD_Result #define _MHD_EXTERN extern #elif defined (_WIN32) && defined(MHD_W32DLL) /* Define MHD_W32DLL when using MHD as W32 .DLL to speed up linker a little */ -#define _MHD_EXTERN __declspec (dllimport) +#define _MHD_EXTERN __declspec(dllimport) #else #define _MHD_EXTERN extern #endif @@ -262,10 +262,10 @@ typedef SOCKET MHD_socket; #ifndef _MHD_DEPR_FUNC #if defined(_MSC_FULL_VER) && _MSC_VER + 0 >= 1400 /* VS 2005 or later */ -#define _MHD_DEPR_FUNC(msg) __declspec (deprecated (msg)) +#define _MHD_DEPR_FUNC(msg) __declspec(deprecated (msg)) #elif defined(_MSC_FULL_VER) && _MSC_VER + 0 >= 1310 /* VS .NET 2003 deprecation do not support custom messages */ -#define _MHD_DEPR_FUNC(msg) __declspec (deprecated) +#define _MHD_DEPR_FUNC(msg) __declspec(deprecated) #elif (__GNUC__ + 0 >= 5) || (defined (__clang__) && \ (__clang_major__ + 0 > 2 || (__clang_major__ + 0 == 2 && __clang_minor__ >= \ 9))) /* FIXME: earlier versions not tested */ @@ -3127,6 +3127,20 @@ MHD_create_response_from_fd (size_t size, /** * Create a response object. The response object can be extended with + * header information and then be used ONLY ONCE. + * + * @param fd file descriptor referring to a read-end of a pipe with the + * data; will be closed when response is destroyed; + * fd should be in 'blocking' mode + * @return NULL on error (i.e. invalid arguments, out of memory) + * @ingroup response + */ +_MHD_EXTERN struct MHD_Response * +MHD_create_response_from_pipe (int fd); + + +/** + * Create a response object. The response object can be extended with * header information and then be used any number of times. * * @param size size of the data portion of the response; diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c @@ -3957,11 +3957,14 @@ MHD_queue_response (struct MHD_Connection *connection, connection->responseCode = status_code; #if defined(_MHD_HAVE_SENDFILE) if ( (response->fd == -1) || + (response->is_pipe) || (0 != (connection->daemon->options & MHD_USE_TLS)) ) connection->resp_sender = MHD_resp_sender_std; else connection->resp_sender = MHD_resp_sender_sendfile; #endif /* _MHD_HAVE_SENDFILE */ + /* FIXME: if 'is_pipe' is set, TLS is off, and we have *splice*, we could use splice() + to avoid two user-space copies... */ if ( ( (NULL != connection->method) && (MHD_str_equal_caseless_ (connection->method, diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h @@ -400,6 +400,11 @@ struct MHD_Response */ enum MHD_ResponseFlags flags; + /** + * If the @e fd is a pipe (no sendfile()). + */ + bool is_pipe; + }; diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c @@ -527,6 +527,37 @@ file_reader (void *cls, /** + * Given a pipe descriptor, read data from the pipe + * to generate the response. + * + * @param cls pointer to the response + * @param pos offset in the pipe to access (ignored) + * @param buf where to write the data + * @param max number of bytes to write at most + * @return number of bytes written + */ +static ssize_t +pipe_reader (void *cls, + uint64_t pos, + char *buf, + size_t max) +{ + struct MHD_Response *response = cls; + ssize_t n; + + (void) pos; + n = read (response->fd, + buf, + max); + if (0 == n) + return MHD_CONTENT_READER_END_OF_STREAM; + if (n < 0) + return MHD_CONTENT_READER_END_WITH_ERROR; + return n; +} + + +/** * Destroy file reader context. Closes the file * descriptor. * @@ -614,6 +645,7 @@ MHD_create_response_from_fd_at_offset64 (uint64_t size, if (NULL == response) return NULL; response->fd = fd; + response->is_pipe = false; response->fd_off = offset; response->crc_cls = response; return response; @@ -622,6 +654,35 @@ MHD_create_response_from_fd_at_offset64 (uint64_t size, /** * Create a response object. The response object can be extended with + * header information and then be used ONLY ONCE. + * + * @param fd file descriptor referring to a read-end of a pipe with the + * data; will be closed when response is destroyed; + * fd should be in 'blocking' mode + * @return NULL on error (i.e. invalid arguments, out of memory) + * @ingroup response + */ +_MHD_EXTERN struct MHD_Response * +MHD_create_response_from_pipe (int fd) +{ + struct MHD_Response *response; + + response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN, + MHD_FILE_READ_BLOCK_SIZE, + &pipe_reader, + NULL, + &free_callback); + if (NULL == response) + return NULL; + response->fd = fd; + response->is_pipe = true; + response->crc_cls = response; + return response; +} + + +/** + * Create a response object. The response object can be extended with * header information and then be used any number of times. * * @param size size of the data portion of the response