diff options
author | Christian Grothoff <christian@grothoff.org> | 2020-07-26 14:15:50 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2020-07-26 14:15:50 +0200 |
commit | 1c4f23db7458d79a04c8e68022ade67cb5ee006b (patch) | |
tree | ca30e21e645f50d9a230ae29ef3cf21056a96279 | |
parent | babda9e9c702aee6e03e7537108383e32a7c17d0 (diff) | |
download | libmicrohttpd-1c4f23db7458d79a04c8e68022ade67cb5ee006b.tar.gz libmicrohttpd-1c4f23db7458d79a04c8e68022ade67cb5ee006b.zip |
add ability to serve files from pipe
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | doc/libmicrohttpd.texi | 15 | ||||
-rw-r--r-- | src/include/microhttpd.h | 20 | ||||
-rw-r--r-- | src/microhttpd/connection.c | 3 | ||||
-rw-r--r-- | src/microhttpd/internal.h | 5 | ||||
-rw-r--r-- | src/microhttpd/response.c | 61 |
6 files changed, 105 insertions, 3 deletions
@@ -1,3 +1,7 @@ | |||
1 | Sun 26 Jul 2020 01:56:54 PM CEST | ||
2 | Add MHD_create_response_from_pipe() to allow creating a response based | ||
3 | on data read from a pipe. -CG | ||
4 | |||
1 | Fri Jul 10 15:04:51 CEST 2020 | 5 | Fri Jul 10 15:04:51 CEST 2020 |
2 | Fixed Postprocessor URL-encoded parsing if '%' fell on boundary. -CG/MD | 6 | Fixed Postprocessor URL-encoded parsing if '%' fell on boundary. -CG/MD |
3 | 7 | ||
diff --git a/doc/libmicrohttpd.texi b/doc/libmicrohttpd.texi index 150dd048..fd776028 100644 --- a/doc/libmicrohttpd.texi +++ b/doc/libmicrohttpd.texi | |||
@@ -2018,6 +2018,21 @@ Return @code{NULL} on error (i.e. invalid arguments, out of memory). | |||
2018 | @end deftypefun | 2018 | @end deftypefun |
2019 | 2019 | ||
2020 | 2020 | ||
2021 | @deftypefun {struct MHD_Response *} MHD_create_response_from_pipe (uint64_t size, int fd) | ||
2022 | Create a response object. The response object can be extended with | ||
2023 | header information and then it can be used ONLY ONCE. | ||
2024 | |||
2025 | @table @var | ||
2026 | @item fd | ||
2027 | file descriptor of the read-end of the pipe; will be | ||
2028 | closed when response is destroyed. | ||
2029 | The descriptor should be in blocking-IO mode. | ||
2030 | @end table | ||
2031 | |||
2032 | Return @code{NULL} on error (i.e. out of memory). | ||
2033 | @end deftypefun | ||
2034 | |||
2035 | |||
2021 | @deftypefun {struct MHD_Response *} MHD_create_response_from_fd_at_offset (size_t size, int fd, off_t offset) | 2036 | @deftypefun {struct MHD_Response *} MHD_create_response_from_fd_at_offset (size_t size, int fd, off_t offset) |
2022 | Create a response object. The response object can be extended with | 2037 | Create a response object. The response object can be extended with |
2023 | header information and then it can be used any number of times. | 2038 | header information and then it can be used any number of times. |
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h index 09983ab7..7aff40f5 100644 --- a/src/include/microhttpd.h +++ b/src/include/microhttpd.h | |||
@@ -180,7 +180,7 @@ enum MHD_Result | |||
180 | #define _MHD_EXTERN extern | 180 | #define _MHD_EXTERN extern |
181 | #elif defined (_WIN32) && defined(MHD_W32DLL) | 181 | #elif defined (_WIN32) && defined(MHD_W32DLL) |
182 | /* Define MHD_W32DLL when using MHD as W32 .DLL to speed up linker a little */ | 182 | /* Define MHD_W32DLL when using MHD as W32 .DLL to speed up linker a little */ |
183 | #define _MHD_EXTERN __declspec (dllimport) | 183 | #define _MHD_EXTERN __declspec(dllimport) |
184 | #else | 184 | #else |
185 | #define _MHD_EXTERN extern | 185 | #define _MHD_EXTERN extern |
186 | #endif | 186 | #endif |
@@ -262,10 +262,10 @@ typedef SOCKET MHD_socket; | |||
262 | #ifndef _MHD_DEPR_FUNC | 262 | #ifndef _MHD_DEPR_FUNC |
263 | #if defined(_MSC_FULL_VER) && _MSC_VER + 0 >= 1400 | 263 | #if defined(_MSC_FULL_VER) && _MSC_VER + 0 >= 1400 |
264 | /* VS 2005 or later */ | 264 | /* VS 2005 or later */ |
265 | #define _MHD_DEPR_FUNC(msg) __declspec (deprecated (msg)) | 265 | #define _MHD_DEPR_FUNC(msg) __declspec(deprecated (msg)) |
266 | #elif defined(_MSC_FULL_VER) && _MSC_VER + 0 >= 1310 | 266 | #elif defined(_MSC_FULL_VER) && _MSC_VER + 0 >= 1310 |
267 | /* VS .NET 2003 deprecation do not support custom messages */ | 267 | /* VS .NET 2003 deprecation do not support custom messages */ |
268 | #define _MHD_DEPR_FUNC(msg) __declspec (deprecated) | 268 | #define _MHD_DEPR_FUNC(msg) __declspec(deprecated) |
269 | #elif (__GNUC__ + 0 >= 5) || (defined (__clang__) && \ | 269 | #elif (__GNUC__ + 0 >= 5) || (defined (__clang__) && \ |
270 | (__clang_major__ + 0 > 2 || (__clang_major__ + 0 == 2 && __clang_minor__ >= \ | 270 | (__clang_major__ + 0 > 2 || (__clang_major__ + 0 == 2 && __clang_minor__ >= \ |
271 | 9))) /* FIXME: earlier versions not tested */ | 271 | 9))) /* FIXME: earlier versions not tested */ |
@@ -3127,6 +3127,20 @@ MHD_create_response_from_fd (size_t size, | |||
3127 | 3127 | ||
3128 | /** | 3128 | /** |
3129 | * Create a response object. The response object can be extended with | 3129 | * Create a response object. The response object can be extended with |
3130 | * header information and then be used ONLY ONCE. | ||
3131 | * | ||
3132 | * @param fd file descriptor referring to a read-end of a pipe with the | ||
3133 | * data; will be closed when response is destroyed; | ||
3134 | * fd should be in 'blocking' mode | ||
3135 | * @return NULL on error (i.e. invalid arguments, out of memory) | ||
3136 | * @ingroup response | ||
3137 | */ | ||
3138 | _MHD_EXTERN struct MHD_Response * | ||
3139 | MHD_create_response_from_pipe (int fd); | ||
3140 | |||
3141 | |||
3142 | /** | ||
3143 | * Create a response object. The response object can be extended with | ||
3130 | * header information and then be used any number of times. | 3144 | * header information and then be used any number of times. |
3131 | * | 3145 | * |
3132 | * @param size size of the data portion of the response; | 3146 | * @param size size of the data portion of the response; |
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c index 7a17c628..ceae1cf8 100644 --- a/src/microhttpd/connection.c +++ b/src/microhttpd/connection.c | |||
@@ -3957,11 +3957,14 @@ MHD_queue_response (struct MHD_Connection *connection, | |||
3957 | connection->responseCode = status_code; | 3957 | connection->responseCode = status_code; |
3958 | #if defined(_MHD_HAVE_SENDFILE) | 3958 | #if defined(_MHD_HAVE_SENDFILE) |
3959 | if ( (response->fd == -1) || | 3959 | if ( (response->fd == -1) || |
3960 | (response->is_pipe) || | ||
3960 | (0 != (connection->daemon->options & MHD_USE_TLS)) ) | 3961 | (0 != (connection->daemon->options & MHD_USE_TLS)) ) |
3961 | connection->resp_sender = MHD_resp_sender_std; | 3962 | connection->resp_sender = MHD_resp_sender_std; |
3962 | else | 3963 | else |
3963 | connection->resp_sender = MHD_resp_sender_sendfile; | 3964 | connection->resp_sender = MHD_resp_sender_sendfile; |
3964 | #endif /* _MHD_HAVE_SENDFILE */ | 3965 | #endif /* _MHD_HAVE_SENDFILE */ |
3966 | /* FIXME: if 'is_pipe' is set, TLS is off, and we have *splice*, we could use splice() | ||
3967 | to avoid two user-space copies... */ | ||
3965 | 3968 | ||
3966 | if ( ( (NULL != connection->method) && | 3969 | if ( ( (NULL != connection->method) && |
3967 | (MHD_str_equal_caseless_ (connection->method, | 3970 | (MHD_str_equal_caseless_ (connection->method, |
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h index 3fdc7e5c..8f0e821a 100644 --- a/src/microhttpd/internal.h +++ b/src/microhttpd/internal.h | |||
@@ -400,6 +400,11 @@ struct MHD_Response | |||
400 | */ | 400 | */ |
401 | enum MHD_ResponseFlags flags; | 401 | enum MHD_ResponseFlags flags; |
402 | 402 | ||
403 | /** | ||
404 | * If the @e fd is a pipe (no sendfile()). | ||
405 | */ | ||
406 | bool is_pipe; | ||
407 | |||
403 | }; | 408 | }; |
404 | 409 | ||
405 | 410 | ||
diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c index 25c05163..27b3ee3f 100644 --- a/src/microhttpd/response.c +++ b/src/microhttpd/response.c | |||
@@ -527,6 +527,37 @@ file_reader (void *cls, | |||
527 | 527 | ||
528 | 528 | ||
529 | /** | 529 | /** |
530 | * Given a pipe descriptor, read data from the pipe | ||
531 | * to generate the response. | ||
532 | * | ||
533 | * @param cls pointer to the response | ||
534 | * @param pos offset in the pipe to access (ignored) | ||
535 | * @param buf where to write the data | ||
536 | * @param max number of bytes to write at most | ||
537 | * @return number of bytes written | ||
538 | */ | ||
539 | static ssize_t | ||
540 | pipe_reader (void *cls, | ||
541 | uint64_t pos, | ||
542 | char *buf, | ||
543 | size_t max) | ||
544 | { | ||
545 | struct MHD_Response *response = cls; | ||
546 | ssize_t n; | ||
547 | |||
548 | (void) pos; | ||
549 | n = read (response->fd, | ||
550 | buf, | ||
551 | max); | ||
552 | if (0 == n) | ||
553 | return MHD_CONTENT_READER_END_OF_STREAM; | ||
554 | if (n < 0) | ||
555 | return MHD_CONTENT_READER_END_WITH_ERROR; | ||
556 | return n; | ||
557 | } | ||
558 | |||
559 | |||
560 | /** | ||
530 | * Destroy file reader context. Closes the file | 561 | * Destroy file reader context. Closes the file |
531 | * descriptor. | 562 | * descriptor. |
532 | * | 563 | * |
@@ -614,6 +645,7 @@ MHD_create_response_from_fd_at_offset64 (uint64_t size, | |||
614 | if (NULL == response) | 645 | if (NULL == response) |
615 | return NULL; | 646 | return NULL; |
616 | response->fd = fd; | 647 | response->fd = fd; |
648 | response->is_pipe = false; | ||
617 | response->fd_off = offset; | 649 | response->fd_off = offset; |
618 | response->crc_cls = response; | 650 | response->crc_cls = response; |
619 | return response; | 651 | return response; |
@@ -622,6 +654,35 @@ MHD_create_response_from_fd_at_offset64 (uint64_t size, | |||
622 | 654 | ||
623 | /** | 655 | /** |
624 | * Create a response object. The response object can be extended with | 656 | * Create a response object. The response object can be extended with |
657 | * header information and then be used ONLY ONCE. | ||
658 | * | ||
659 | * @param fd file descriptor referring to a read-end of a pipe with the | ||
660 | * data; will be closed when response is destroyed; | ||
661 | * fd should be in 'blocking' mode | ||
662 | * @return NULL on error (i.e. invalid arguments, out of memory) | ||
663 | * @ingroup response | ||
664 | */ | ||
665 | _MHD_EXTERN struct MHD_Response * | ||
666 | MHD_create_response_from_pipe (int fd) | ||
667 | { | ||
668 | struct MHD_Response *response; | ||
669 | |||
670 | response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN, | ||
671 | MHD_FILE_READ_BLOCK_SIZE, | ||
672 | &pipe_reader, | ||
673 | NULL, | ||
674 | &free_callback); | ||
675 | if (NULL == response) | ||
676 | return NULL; | ||
677 | response->fd = fd; | ||
678 | response->is_pipe = true; | ||
679 | response->crc_cls = response; | ||
680 | return response; | ||
681 | } | ||
682 | |||
683 | |||
684 | /** | ||
685 | * Create a response object. The response object can be extended with | ||
625 | * header information and then be used any number of times. | 686 | * header information and then be used any number of times. |
626 | * | 687 | * |
627 | * @param size size of the data portion of the response | 688 | * @param size size of the data portion of the response |