add ability to serve files from pipe

This commit is contained in:
Christian Grothoff
2020-07-26 14:15:50 +02:00
parent babda9e9c7
commit 1c4f23db74
6 changed files with 105 additions and 3 deletions
+4
View File
@@ -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
+15
View File
@@ -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.
+17 -3
View File
@@ -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 */
@@ -3125,6 +3125,20 @@ MHD_create_response_from_fd (size_t size,
int fd);
/**
* 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.
+3
View File
@@ -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,
+5
View File
@@ -400,6 +400,11 @@ struct MHD_Response
*/
enum MHD_ResponseFlags flags;
/**
* If the @e fd is a pipe (no sendfile()).
*/
bool is_pipe;
};
+61
View File
@@ -526,6 +526,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,12 +645,42 @@ 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;
}
/**
* 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.