mirror of
https://git.gnunet.org/libmicrohttpd.git
synced 2026-09-25 04:09:31 +03:00
Implemented fallback file reader for the responses
This commit is contained in:
+21
-3
@@ -4526,10 +4526,16 @@ AM_CONDITIONAL([MHD_HAVE_LIBMAGIC], [[test "x$mhd_cv_have_func_magic_open" = "xy
|
||||
# large file support (> 4 GB)
|
||||
MHD_CHECK_FUNC([lseek64],
|
||||
[[
|
||||
#ifndef _LARGEFILE64_SOURCE
|
||||
# define _LARGEFILE64_SOURCE 1
|
||||
#endif
|
||||
#if defined(HAVE_SYS_TYPES_H)
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
]],
|
||||
[[
|
||||
i][f (((off64_t) -1) == lseek64(0, (off64_t) 0, SEEK_SET))
|
||||
@@ -4538,10 +4544,16 @@ MHD_CHECK_FUNC([lseek64],
|
||||
)
|
||||
MHD_CHECK_FUNC([pread64],
|
||||
[[
|
||||
#ifndef _LARGEFILE64_SOURCE
|
||||
# define _LARGEFILE64_SOURCE 1
|
||||
#endif
|
||||
#if defined(HAVE_SYS_TYPES_H)
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
]],
|
||||
[[
|
||||
char buf[5];
|
||||
@@ -4554,7 +4566,10 @@ MHD_CHECK_FUNC([pread],
|
||||
#if defined(HAVE_SYS_TYPES_H)
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
]],
|
||||
[[
|
||||
char buf[5];
|
||||
@@ -4608,6 +4623,9 @@ static void empty_func(void)
|
||||
AC_MSG_RESULT([[yes]])
|
||||
MHD_CHECK_FUNC([sendfile64],
|
||||
[[
|
||||
#ifndef _LARGEFILE64_SOURCE
|
||||
# define _LARGEFILE64_SOURCE 1
|
||||
#endif
|
||||
#include <sys/sendfile.h>
|
||||
]],
|
||||
[[
|
||||
|
||||
@@ -332,6 +332,13 @@
|
||||
# endif
|
||||
#endif /* mhd_THREADS_KIND_POSIX || mhd_THREADS_KIND_W32 */
|
||||
|
||||
#if defined(_WIN32) && ! defined(__CYGWIN__)
|
||||
/**
|
||||
* Defined if the platform is native W32.
|
||||
* Not define on Cygwin.
|
||||
*/
|
||||
# define mhd_W32_NATIVE 1
|
||||
#endif
|
||||
/**
|
||||
* Macro to drop 'const' qualifier from pointer.
|
||||
* Try to avoid compiler warning.
|
||||
@@ -401,10 +408,12 @@
|
||||
#define RESTRICT __restrict__
|
||||
#endif /* __VXWORKS__ || __vxworks || OS_VXWORKS */
|
||||
|
||||
#if defined(LINUX) && (defined(HAVE_SENDFILE64) || defined(HAVE_LSEEK64)) && \
|
||||
! defined(_LARGEFILE64_SOURCE)
|
||||
#if defined(__linux__) && \
|
||||
(defined(HAVE_SENDFILE64) || defined(HAVE_LSEEK64) || defined(HAVE_PREAD64))
|
||||
# if ! defined(_LARGEFILE64_SOURCE)
|
||||
/* On Linux, special macro is required to enable definitions of some xxx64 functions */
|
||||
#define _LARGEFILE64_SOURCE 1
|
||||
# define _LARGEFILE64_SOURCE 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_C11_GMTIME_S
|
||||
|
||||
@@ -1152,6 +1152,11 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
|
||||
*/
|
||||
MHD_SC_REPLY_POOL_ALLOCATION_FAILURE = 50231
|
||||
,
|
||||
/**
|
||||
* Failed to read the file for file-backed response.
|
||||
*/
|
||||
MHD_SC_REPLY_FILE_READ_ERROR = 50232
|
||||
,
|
||||
/**
|
||||
* Failed to allocate memory in connection's pool for the reply.
|
||||
*/
|
||||
@@ -1457,6 +1462,18 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
|
||||
*/
|
||||
MHD_SC_REPLY_HEADERS_TOO_LARGE = 60103
|
||||
,
|
||||
/**
|
||||
* Specified offset in file-backed response is too large and not supported
|
||||
* by the platform
|
||||
*/
|
||||
MHD_SC_REPLY_FILE_OFFSET_TOO_LARGE = 60104
|
||||
,
|
||||
/**
|
||||
* File-backed response has file smaller than specified combination of
|
||||
* the file offset and the response size.
|
||||
*/
|
||||
MHD_SC_REPLY_FILE_TOO_SHORT = 60105
|
||||
,
|
||||
/**
|
||||
* The new connection cannot be used because the FD number is higher than
|
||||
* the limit set by FD_SETSIZE (if internal polling with select is used) or
|
||||
@@ -3734,8 +3751,7 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_RequestEndedCode
|
||||
MHD_REQUEST_ENDED_CLIENT_ABORT = 30
|
||||
,
|
||||
/**
|
||||
* The request is not valid according to
|
||||
* HTTP specifications.
|
||||
* The request is not valid according to HTTP specifications.
|
||||
* @ingroup request
|
||||
*/
|
||||
MHD_REQUEST_ENDED_HTTP_PROTOCOL_ERROR = 31
|
||||
@@ -3747,7 +3763,8 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_RequestEndedCode
|
||||
MHD_REQUEST_ENDED_BY_APP_ABORT = 40
|
||||
,
|
||||
/**
|
||||
* The application aborted request without response.
|
||||
* The request was aborted due to the application failed to provide a valid
|
||||
* resonse.
|
||||
* @ingroup request
|
||||
*/
|
||||
MHD_REQUEST_ENDED_BY_APP_ERROR = 41
|
||||
@@ -3758,6 +3775,12 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_RequestEndedCode
|
||||
*/
|
||||
MHD_REQUEST_ENDED_NO_RESOURCES = 50
|
||||
,
|
||||
/**
|
||||
* The request was aborted due to error reading file for file-backed response
|
||||
* @ingroup request
|
||||
*/
|
||||
MHD_REQUEST_ENDED_FILE_ERROR = 51
|
||||
,
|
||||
/**
|
||||
* Closing the session since MHD is being shut down.
|
||||
* @ingroup request
|
||||
|
||||
@@ -1152,6 +1152,11 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
|
||||
*/
|
||||
MHD_SC_REPLY_POOL_ALLOCATION_FAILURE = 50231
|
||||
,
|
||||
/**
|
||||
* Failed to read the file for file-backed response.
|
||||
*/
|
||||
MHD_SC_REPLY_FILE_READ_ERROR = 50232
|
||||
,
|
||||
/**
|
||||
* Failed to allocate memory in connection's pool for the reply.
|
||||
*/
|
||||
@@ -1457,6 +1462,18 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
|
||||
*/
|
||||
MHD_SC_REPLY_HEADERS_TOO_LARGE = 60103
|
||||
,
|
||||
/**
|
||||
* Specified offset in file-backed response is too large and not supported
|
||||
* by the platform
|
||||
*/
|
||||
MHD_SC_REPLY_FILE_OFFSET_TOO_LARGE = 60104
|
||||
,
|
||||
/**
|
||||
* File-backed response has file smaller than specified combination of
|
||||
* the file offset and the response size.
|
||||
*/
|
||||
MHD_SC_REPLY_FILE_TOO_SHORT = 60105
|
||||
,
|
||||
/**
|
||||
* The new connection cannot be used because the FD number is higher than
|
||||
* the limit set by FD_SETSIZE (if internal polling with select is used) or
|
||||
@@ -3734,8 +3751,7 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_RequestEndedCode
|
||||
MHD_REQUEST_ENDED_CLIENT_ABORT = 30
|
||||
,
|
||||
/**
|
||||
* The request is not valid according to
|
||||
* HTTP specifications.
|
||||
* The request is not valid according to HTTP specifications.
|
||||
* @ingroup request
|
||||
*/
|
||||
MHD_REQUEST_ENDED_HTTP_PROTOCOL_ERROR = 31
|
||||
@@ -3747,7 +3763,8 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_RequestEndedCode
|
||||
MHD_REQUEST_ENDED_BY_APP_ABORT = 40
|
||||
,
|
||||
/**
|
||||
* The application aborted request without response.
|
||||
* The request was aborted due to the application failed to provide a valid
|
||||
* resonse.
|
||||
* @ingroup request
|
||||
*/
|
||||
MHD_REQUEST_ENDED_BY_APP_ERROR = 41
|
||||
@@ -3758,6 +3775,12 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_RequestEndedCode
|
||||
*/
|
||||
MHD_REQUEST_ENDED_NO_RESOURCES = 50
|
||||
,
|
||||
/**
|
||||
* The request was aborted due to error reading file for file-backed response
|
||||
* @ingroup request
|
||||
*/
|
||||
MHD_REQUEST_ENDED_FILE_ERROR = 51
|
||||
,
|
||||
/**
|
||||
* Closing the session since MHD is being shut down.
|
||||
* @ingroup request
|
||||
|
||||
@@ -55,6 +55,7 @@ libmicrohttpd2_la_SOURCES = \
|
||||
mhd_threads.c mhd_threads.h sys_thread_entry_type.h \
|
||||
mhd_mono_clock.c mhd_mono_clock.h \
|
||||
mhd_mempool.c mhd_mempool.h \
|
||||
mhd_read_file.c mhd_read_file.h \
|
||||
mhd_recv.c mhd_recv.h \
|
||||
mhd_send.c mhd_send.h \
|
||||
mhd_daemon.h \
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
This file is part of GNU libmicrohttpd
|
||||
Copyright (C) 2024 Evgeny Grin (Karlson2k)
|
||||
|
||||
GNU libmicrohttpd is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
GNU libmicrohttpd is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file src/mhd2/mhd_read_file.c
|
||||
* @brief The implementation of mhd_read_file() function
|
||||
* @author Karlson2k (Evgeny Grin)
|
||||
*/
|
||||
|
||||
#include "mhd_sys_options.h"
|
||||
|
||||
#include "mhd_read_file.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if ! defined(mhd_W32_NATIVE)
|
||||
# include "mhd_limits.h"
|
||||
#else
|
||||
/* Native W32 */
|
||||
# include <windows.h>
|
||||
# include <string.h> /* for memset() */
|
||||
#endif
|
||||
/**
|
||||
* Read data from the file to the provided buffer
|
||||
*
|
||||
* @param file_fd the FD of file to read
|
||||
* @param buf_size the size of the @a buf buffer
|
||||
* @param[out] buf the buffer to fill with the read data
|
||||
* @param[out] size_filled the pointer to variable to get the size of the data
|
||||
* actually put to the @a buffer
|
||||
* @return #mhd_FILE_READ_OK if succeed (the @a size_filled gets the actual
|
||||
* read size),
|
||||
* error otherwise
|
||||
*/
|
||||
MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
|
||||
MHD_FN_PAR_OUT_SIZE_ (4, 3) MHD_FN_PAR_OUT_ (5) enum mhd_FileReadResult
|
||||
mhd_read_file (int file_fd,
|
||||
uint_fast64_t offset,
|
||||
size_t buf_size,
|
||||
char buf[MHD_FN_PAR_DYN_ARR_SIZE_ (buf_size)],
|
||||
size_t *restrict size_filled)
|
||||
{
|
||||
#if (defined(HAVE_PREAD64) || defined(HAVE_PREAD)) && ! defined(mhd_W32_NATIVE)
|
||||
# ifdef HAVE_PREAD64
|
||||
const off64_t pos_off = (off64_t) offset;
|
||||
# else /* HAVE_PREAD */
|
||||
const off_t pos_off = (off_t) offset;
|
||||
# endif /* HAVE_PREAD */
|
||||
ssize_t res;
|
||||
|
||||
*size_filled = 0;
|
||||
|
||||
if ((0 > pos_off) ||
|
||||
(offset != (uint_fast64_t) pos_off))
|
||||
return mhd_FILE_READ_OFFSET_TOO_LARGE;
|
||||
|
||||
if (0 > (ssize_t) buf_size)
|
||||
buf_size = SSIZE_MAX; /* Larger sizes may result in undefined behaviour */
|
||||
|
||||
# ifdef HAVE_PREAD64
|
||||
res = pread64 (file_fd,
|
||||
buf,
|
||||
buf_size,
|
||||
pos_off);
|
||||
# else /* HAVE_PREAD */
|
||||
res = pread (file_fd,
|
||||
buf,
|
||||
buf_size,
|
||||
pos_off);
|
||||
# endif /* HAVE_PREAD */
|
||||
|
||||
if (0 > res)
|
||||
return mhd_FILE_READ_ERROR;
|
||||
|
||||
if (0 == res)
|
||||
return mhd_FILE_READ_EOF;
|
||||
|
||||
*size_filled = (size_t) res;
|
||||
return mhd_FILE_READ_OK;
|
||||
#elif ! defined(mhd_W32_NATIVE)
|
||||
/* Multithread-unsafe emulation */
|
||||
# ifdef HAVE_LSEEK64
|
||||
const off64_t pos_off = (off64_t) offset;
|
||||
# else
|
||||
const off_t pos_off = (off_t) offset;
|
||||
# endif
|
||||
ssize_t res;
|
||||
|
||||
*size_filled = 0;
|
||||
|
||||
if ((0 > pos_off) ||
|
||||
(offset != (uint_fast64_t) pos_off))
|
||||
return mhd_FILE_READ_OFFSET_TOO_LARGE;
|
||||
|
||||
if (0 > (ssize_t) buf_size)
|
||||
buf_size = SSIZE_MAX; /* Larger sizes may result in undefined behaviour */
|
||||
|
||||
# ifdef HAVE_LSEEK64
|
||||
if (pos_off != lseek64 (file_fd,
|
||||
pos_off,
|
||||
SEEK_SET))
|
||||
return mhd_FILE_READ_ERROR;
|
||||
# else
|
||||
if (pos_off != lseek (file_fd,
|
||||
pos_off,
|
||||
SEEK_SET))
|
||||
return mhd_FILE_READ_ERROR;
|
||||
# endif
|
||||
|
||||
res = read (file_fd,
|
||||
buf,
|
||||
buf_size);
|
||||
|
||||
if (0 > res)
|
||||
return mhd_FILE_READ_ERROR;
|
||||
|
||||
if (0 == res)
|
||||
return mhd_FILE_READ_EOF;
|
||||
|
||||
*size_filled = (size_t) res;
|
||||
return mhd_FILE_READ_OK;
|
||||
|
||||
#else /* Native W32 */
|
||||
const intptr_t sys_fd = _get_osfhandle (file_fd);
|
||||
const HANDLE w_hndl = (HANDLE) sys_fd;
|
||||
OVERLAPPED ovrlp;
|
||||
DWORD reqReadSize;
|
||||
DWORD resReadSize;
|
||||
|
||||
*size_filled = 0;
|
||||
if (INVALID_HANDLE_VALUE == w_hndl)
|
||||
return mhd_FILE_READ_ERROR;
|
||||
|
||||
memset (&ovrlp, 0, sizeof(ovrlp));
|
||||
reqReadSize = (DWORD) buf_size;
|
||||
if (reqReadSize != buf_size)
|
||||
reqReadSize = (DWORD) (~((DWORD) 0));
|
||||
ovrlp.Offset = (DWORD) offset;
|
||||
offset >>= 32;
|
||||
ovrlp.OffsetHigh = (DWORD) offset;
|
||||
if (0 != (offset >> 32))
|
||||
return mhd_FILE_READ_OFFSET_TOO_LARGE;
|
||||
|
||||
if (! ReadFile (w_hndl,
|
||||
buf,
|
||||
reqReadSize,
|
||||
&resReadSize,
|
||||
&ovrlp))
|
||||
return mhd_FILE_READ_ERROR;
|
||||
|
||||
if (0 == resReadSize)
|
||||
return mhd_FILE_READ_EOF;
|
||||
|
||||
*size_filled = resReadSize;
|
||||
return mhd_FILE_READ_OK;
|
||||
#endif /* Native W32 */
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
This file is part of GNU libmicrohttpd
|
||||
Copyright (C) 2024 Evgeny Grin (Karlson2k)
|
||||
|
||||
GNU libmicrohttpd is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
GNU libmicrohttpd is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file src/mhd2/mhd_read_file.h
|
||||
* @brief The declaration of mhd_read_file() function
|
||||
* @author Karlson2k (Evgeny Grin)
|
||||
*/
|
||||
|
||||
#ifndef MHD_READ_FILE_H
|
||||
#define MHD_READ_FILE_H 1
|
||||
|
||||
#include "mhd_sys_options.h"
|
||||
|
||||
#include "sys_base_types.h"
|
||||
|
||||
/**
|
||||
* Results of file reading
|
||||
*/
|
||||
enum mhd_FileReadResult
|
||||
{
|
||||
/**
|
||||
* File read succeed
|
||||
*/
|
||||
mhd_FILE_READ_OK = 0
|
||||
,
|
||||
/**
|
||||
* File read failed
|
||||
*/
|
||||
mhd_FILE_READ_ERROR
|
||||
,
|
||||
/**
|
||||
* The requested offset is too large
|
||||
*/
|
||||
mhd_FILE_READ_OFFSET_TOO_LARGE
|
||||
,
|
||||
/**
|
||||
* Got "end of file"
|
||||
*/
|
||||
mhd_FILE_READ_EOF
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read data from the file to the provided buffer
|
||||
*
|
||||
* @param file_fd the FD of file to read
|
||||
* @param buf_size the size of the @a buf buffer
|
||||
* @param[out] buf the buffer to fill with the read data
|
||||
* @param[out] size_filled the pointer to variable to get the size of the data
|
||||
* actually put to the @a buffer
|
||||
* @return #mhd_FILE_READ_OK if succeed (the @a size_filled gets the actual
|
||||
* read size),
|
||||
* error otherwise
|
||||
*/
|
||||
MHD_INTERNAL enum mhd_FileReadResult
|
||||
mhd_read_file (int file_fd,
|
||||
uint_fast64_t offset,
|
||||
size_t buf_size,
|
||||
char buf[MHD_FN_PAR_DYN_ARR_SIZE_ (buf_size)],
|
||||
size_t *restrict size_filled)
|
||||
MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
|
||||
MHD_FN_PAR_OUT_SIZE_(4, 3) MHD_FN_PAR_OUT_ (5);
|
||||
|
||||
|
||||
#endif /* ! MHD_READ_FILE_H */
|
||||
@@ -720,6 +720,21 @@ mhd_conn_start_closing (struct MHD_Connection *restrict c,
|
||||
end_code = MHD_REQUEST_ENDED_BY_APP_ABORT;
|
||||
sc = MHD_SC_APPLICATION_CALLBACK_ABORT_ACTION;
|
||||
break;
|
||||
case mhd_CONN_CLOSE_FILE_OFFSET_TOO_LARGE:
|
||||
close_hard = true;
|
||||
end_code = MHD_REQUEST_ENDED_FILE_ERROR;
|
||||
sc = MHD_SC_REPLY_FILE_OFFSET_TOO_LARGE;
|
||||
break;
|
||||
case mhd_CONN_CLOSE_FILE_READ_ERROR:
|
||||
close_hard = true;
|
||||
end_code = MHD_REQUEST_ENDED_FILE_ERROR;
|
||||
sc = MHD_SC_REPLY_FILE_READ_ERROR;
|
||||
break;
|
||||
case mhd_CONN_CLOSE_FILE_TOO_SHORT:
|
||||
close_hard = true;
|
||||
end_code = MHD_REQUEST_ENDED_BY_APP_ERROR;
|
||||
sc = MHD_SC_REPLY_FILE_TOO_SHORT;
|
||||
break;
|
||||
case mhd_CONN_CLOSE_INT_ERROR:
|
||||
close_hard = true;
|
||||
end_code = MHD_REQUEST_ENDED_NO_RESOURCES;
|
||||
|
||||
@@ -198,6 +198,21 @@ enum mhd_ConnCloseReason
|
||||
*/
|
||||
mhd_CONN_CLOSE_APP_ABORTED
|
||||
,
|
||||
/**
|
||||
* File-backed response too large (unsupported by OS) file offset
|
||||
*/
|
||||
mhd_CONN_CLOSE_FILE_OFFSET_TOO_LARGE
|
||||
,
|
||||
/**
|
||||
* Error reading file-backed response
|
||||
*/
|
||||
mhd_CONN_CLOSE_FILE_READ_ERROR
|
||||
,
|
||||
/**
|
||||
* File-backed response has file smaller than specified by application
|
||||
*/
|
||||
mhd_CONN_CLOSE_FILE_TOO_SHORT
|
||||
,
|
||||
|
||||
/* Hard problem while receiving or sending */
|
||||
/**
|
||||
|
||||
@@ -53,6 +53,8 @@
|
||||
#include "stream_funcs.h"
|
||||
#include "request_get_value.h"
|
||||
|
||||
#include "mhd_read_file.h"
|
||||
|
||||
#include "mhd_public_api.h"
|
||||
|
||||
MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void
|
||||
@@ -964,6 +966,67 @@ preprocess_dcc_action (struct MHD_Connection *restrict c,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read next portion of the response file to the buffer, based on information
|
||||
* about amount of response content position.
|
||||
* Handle file read errors, update response position.
|
||||
* @param c the stream to use
|
||||
* @param r the response to use
|
||||
* @param buf_size the size of the @a buf buffer
|
||||
* @param[out] buf the buffer to fill with the file data
|
||||
* @param[out] size_filled the pointer to variable to get the size of the data
|
||||
* actually put to the @a buffer
|
||||
* @return 'true' if succeed (size_filled and response position are updated),
|
||||
* 'false' if failed (the stream is closed)
|
||||
*/
|
||||
static MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
|
||||
MHD_FN_PAR_OUT_SIZE_ (4, 3) MHD_FN_PAR_OUT_ (5) bool
|
||||
read_response_file (struct MHD_Connection *restrict c,
|
||||
struct MHD_Response *const restrict r,
|
||||
size_t buf_size,
|
||||
char buf[MHD_FN_PAR_DYN_ARR_SIZE_ (buf_size)],
|
||||
size_t *restrict size_filled)
|
||||
{
|
||||
mhd_assert (r == c->rp.response);
|
||||
mhd_assert (mhd_RESPONSE_CONTENT_DATA_FILE == r->cntn_dtype);
|
||||
|
||||
switch (mhd_read_file (r->cntn.file.fd,
|
||||
r->cntn.file.offset + c->rp.rsp_cntn_read_pos,
|
||||
buf_size,
|
||||
buf,
|
||||
size_filled))
|
||||
{
|
||||
case mhd_FILE_READ_OK:
|
||||
break;
|
||||
case mhd_FILE_READ_ERROR:
|
||||
mhd_STREAM_ABORT (c, \
|
||||
mhd_CONN_CLOSE_FILE_READ_ERROR, \
|
||||
"Error reading file for file-backed response.");
|
||||
return false;
|
||||
case mhd_FILE_READ_OFFSET_TOO_LARGE:
|
||||
mhd_STREAM_ABORT (c, \
|
||||
mhd_CONN_CLOSE_FILE_OFFSET_TOO_LARGE, \
|
||||
"The offset for file-backed response is too large " \
|
||||
"for this platform.");
|
||||
return false;
|
||||
case mhd_FILE_READ_EOF:
|
||||
mhd_STREAM_ABORT (c, \
|
||||
mhd_CONN_CLOSE_FILE_TOO_SHORT, \
|
||||
"The file for file-backed response is smaller " \
|
||||
"than specified by application.");
|
||||
return false;
|
||||
default:
|
||||
mhd_assert (0 && "Impossible value");
|
||||
MHD_UNREACHABLE_;
|
||||
c->rp.cntn_loc = mhd_REPLY_CNTN_LOC_NOWHERE;
|
||||
return false;
|
||||
}
|
||||
|
||||
c->rp.rsp_cntn_read_pos += *size_filled;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ bool
|
||||
mhd_stream_prep_unchunked_body (struct MHD_Connection *restrict c)
|
||||
{
|
||||
@@ -1049,10 +1112,21 @@ mhd_stream_prep_unchunked_body (struct MHD_Connection *restrict c)
|
||||
}
|
||||
else if (mhd_RESPONSE_CONTENT_DATA_FILE == r->cntn_dtype)
|
||||
{
|
||||
// TODO: implement fallback
|
||||
mhd_assert (0 && "Not implemented yet");
|
||||
c->rp.cntn_loc = mhd_REPLY_CNTN_LOC_NOWHERE;
|
||||
c->rp.rsp_cntn_read_pos = r->cntn_size;
|
||||
size_t size_to_fill =
|
||||
c->write_buffer_size - c->write_buffer_append_offset;
|
||||
size_t filled;
|
||||
|
||||
if (size_to_fill > left_to_send)
|
||||
size_to_fill = (size_t) left_to_send;
|
||||
|
||||
if (! read_response_file (c,
|
||||
r,
|
||||
size_to_fill,
|
||||
c->write_buffer + c->write_buffer_append_offset,
|
||||
&filled))
|
||||
return true; /* Error, the stream is closed */
|
||||
|
||||
c->write_buffer_append_offset += filled;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1061,10 +1135,6 @@ mhd_stream_prep_unchunked_body (struct MHD_Connection *restrict c)
|
||||
c->rp.cntn_loc = mhd_REPLY_CNTN_LOC_NOWHERE;
|
||||
c->rp.rsp_cntn_read_pos = r->cntn_size;
|
||||
}
|
||||
|
||||
mhd_assert (0 && "Not implemented yet");
|
||||
c->rp.cntn_loc = mhd_REPLY_CNTN_LOC_NOWHERE;
|
||||
c->rp.rsp_cntn_read_pos = r->cntn_size;
|
||||
}
|
||||
else if (mhd_REPLY_CNTN_LOC_IOV == c->rp.cntn_loc)
|
||||
{
|
||||
@@ -1215,6 +1285,17 @@ mhd_stream_prep_chunked_body (struct MHD_Connection *restrict c)
|
||||
c->rp.rsp_cntn_read_pos += filled;
|
||||
c->write_buffer_append_offset += filled;
|
||||
}
|
||||
else if (mhd_RESPONSE_CONTENT_DATA_FILE == r->cntn_dtype)
|
||||
{
|
||||
if (! read_response_file (c,
|
||||
r,
|
||||
size_to_fill,
|
||||
c->write_buffer + max_chunk_hdr_len,
|
||||
&filled))
|
||||
return true; /* Error, the stream is closed */
|
||||
|
||||
c->write_buffer_append_offset += filled;
|
||||
}
|
||||
else
|
||||
{
|
||||
mhd_assert (0 && "Not implemented yet");
|
||||
|
||||
Reference in New Issue
Block a user