summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2020-07-26 14:15:50 +0200
committerChristian Grothoff <christian@grothoff.org>2020-07-26 14:15:50 +0200
commit1c4f23db7458d79a04c8e68022ade67cb5ee006b (patch)
treeca30e21e645f50d9a230ae29ef3cf21056a96279
parentbabda9e9c702aee6e03e7537108383e32a7c17d0 (diff)
add ability to serve files from pipe
-rw-r--r--ChangeLog4
-rw-r--r--doc/libmicrohttpd.texi15
-rw-r--r--src/include/microhttpd.h20
-rw-r--r--src/microhttpd/connection.c3
-rw-r--r--src/microhttpd/internal.h5
-rw-r--r--src/microhttpd/response.c61
6 files changed, 105 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index ebbe7994..a2e24c02 100644
--- 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
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).
@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
index 09983ab7..7aff40f5 100644
--- 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
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,
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
index 3fdc7e5c..8f0e821a 100644
--- 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
index 25c05163..27b3ee3f 100644
--- 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